Anda tidak benar-benar membutuhkan banyak kode:
IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS
Mendukung spasi dalam elemen (selama itu bukan baris baru), dan berfungsi di Bash 3.x.
misalnya:
$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]
Catatan: @sorontar telah menunjukkan bahwa kehati-hatian diperlukan jika elemen berisi karakter pengganti seperti *
atau ?
:
Bagian diurutkan = ($ (...)) menggunakan operator "split and glob". Anda harus mematikan glob: set -f
atau set -o noglob
atau shopt -op noglob
atau elemen dari array *
akan diperluas ke daftar file.
Apa yang terjadi:
Hasilnya adalah enam hal puncak yang terjadi dalam urutan ini:
IFS=$'\n'
"${array[*]}"
<<<
sort
sorted=($(...))
unset IFS
Pertama, IFS=$'\n'
Ini adalah bagian penting dari operasi kami yang memengaruhi hasil 2 dan 5 dengan cara berikut:
Diberikan:
"${array[*]}"
meluas ke setiap elemen yang dibatasi oleh karakter pertama IFS
sorted=()
membuat elemen dengan memisahkan setiap karakter IFS
IFS=$'\n'
mengatur segala sesuatunya sehingga elemen diperluas menggunakan baris baru sebagai pemisah, dan kemudian dibuat sedemikian rupa sehingga setiap baris menjadi elemen. (yaitu Memisahkan di baris baru.)
Membatasi dengan baris baru penting karena begitulah cara sort
kerjanya (pengurutan per baris). Memisahkan hanya dengan baris baru tidak begitu penting, tetapi diperlukan untuk mempertahankan elemen yang berisi spasi atau tab.
Nilai defaultnya IFS
adalah spasi , tab , diikuti oleh baris baru , dan tidak sesuai untuk operasi kita.
Selanjutnya, sort <<<"${array[*]}"
bagian
<<<
, disebut di sini string , mengambil perluasan dari "${array[*]}"
, seperti dijelaskan di atas, dan memasukkannya ke dalam input standar sort
.
Dengan contoh kami, sort
diberi makan string berikut ini:
a c
b
f
3 5
Sejak sort
diurutkan , menghasilkan:
3 5
a c
b
f
Selanjutnya, sorted=($(...))
bagian
Bagian $(...)
, yang disebut substitusi perintah , menyebabkan kontennya ( sort <<<"${array[*]}
) berjalan sebagai perintah normal, sementara mengambil keluaran standar yang dihasilkan sebagai literal yang berjalan di mana pun $(...)
.
Dalam contoh kami, ini menghasilkan sesuatu yang mirip dengan sekadar menulis:
sorted=(3 5
a c
b
f
)
sorted
then becomes an array that's created by splitting this literal on every new line.
Finally, the unset IFS
This resets the value of IFS
to the default value, and is just good practice.
It's to ensure we don't cause trouble with anything that relies on IFS
later in our script. (Otherwise we'd need to remember that we've switched things around--something that might be impractical for complex scripts.)
IFS
, it'll split your elements into little pieces if they have whitespaces in them. Try the e.g. withIFS=$'\n'
omitted and see!