Shell seperti Bourne / POSIX memiliki operator glob + split dan dipanggil setiap kali Anda meninggalkan ekspansi parameter ( $var, $-...), substitusi perintah ( $(...)), atau ekspansi aritmatika ( $((...))) tidak dikutip dalam konteks daftar.
Sebenarnya, Anda dipanggil oleh kesalahan ketika Anda melakukan for name in ${array[@]}bukan for name in "${array[@]}". (Sebenarnya, Anda harus berhati-hati bahwa memanggil operator seperti itu secara tidak sengaja merupakan sumber dari banyak bug dan kerentanan keamanan ).
Operator itu dikonfigurasikan dengan $IFSparameter khusus (untuk memberi tahu karakter apa yang harus dipisah (meskipun berhati-hatilah bahwa ruang, tab, dan baris baru menerima perlakuan khusus di sana)) dan -fopsi untuk menonaktifkan ( set -f) atau mengaktifkan ( set +f) globbagian.
Perhatikan juga bahwa sementara Sin $IFSawalnya (dalam cangkang Bourne dari mana $IFS) dari untuk Separator, dalam cangkang POSIX, karakter dalam $IFSseharusnya lebih dilihat sebagai pembatas atau terminator (lihat di bawah untuk contoh).
Jadi untuk dibagi _:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
array=($string) # invoke the split+glob operator
for i in "${array[@]}"; do # loop over the array elements.
Untuk melihat perbedaan antara pemisah dan pembatas , coba:
string='var1_var2_'
Itu akan membaginya menjadi var1dan var2hanya (tidak ada elemen kosong tambahan).
Jadi, untuk membuatnya mirip dengan JavaScript split(), Anda perlu langkah ekstra:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
temp=${string}_ # add an extra delimiter
array=($temp) # invoke the split+glob operator
(perhatikan bahwa itu akan membagi elemen kosong $stringmenjadi 1 (bukan 0 ), seperti JavaScript split()).
Untuk melihat tab perawatan khusus, ruang dan baris baru terima, bandingkan:
IFS=' '; string=' var1 var2 '
(di mana Anda dapatkan var1dan var2) dengan
IFS='_'; string='_var1__var2__'
di mana Anda mendapatkan: '', var1, '', var2, ''.
Perhatikan bahwa zshshell tidak memanggil operator glob + split yang secara implisit seperti itu kecuali dalam shatau kshemulasi. Di sana, Anda harus memohonnya dengan jelas. $=stringuntuk bagian split, $~stringuntuk bagian glob ( $=~stringuntuk keduanya), dan juga memiliki operator split di mana Anda dapat menentukan pemisah:
array=(${(s:_:)string})
atau untuk melestarikan elemen kosong:
array=("${(@s:_:)string}")
Perhatikan bahwa ada sadalah untuk membelah , bukan pembatasan (juga dengan $IFS, yang dikenal POSIX ketidaksesuaian dari zsh). Ini berbeda dari JavaScript split()karena string kosong dipecah menjadi elemen 0 (bukan 1).
Perbedaan penting dengan $IFS-sitting adalah bahwa ${(s:abc:)string}splits pada abcstring, sedangkan dengan IFS=abc, yang akan terpecah a, batau c.
Dengan zshdan ksh93, perlakuan khusus yang diterima ruang, tab, atau baris baru dapat dihapus dengan menggandakannya $IFS.
Sebagai catatan bersejarah, cangkang Bourne (leluhur atau cangkang POSIX modern) selalu menghilangkan elemen-elemen yang kosong. Itu juga memiliki sejumlah bug yang terkait dengan pemisahan dan perluasan $ @ dengan nilai-nilai non-default $IFS. Misalnya IFS=_; set -f; set -- $@tidak akan setara dengan IFS=_; set -f; set -- $1 $2 $3....
Berpisah pada regexps
Sekarang untuk sesuatu yang lebih dekat dengan JavaScript split()yang dapat terpecah pada ekspresi reguler, Anda harus bergantung pada utilitas eksternal.
Dalam peti alat POSIX, awkmemiliki splitoperator yang dapat membagi pada ekspresi reguler yang diperluas (yang lebih atau kurang merupakan subset dari ekspresi reguler Perl-seperti yang didukung oleh JavaScript).
split() {
awk -v q="'" '
function quote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split(ARGV[1], a, ARGV[2])
for (i = 1; i <= n; i++) printf " %s", quote(a[i])
exit
}' "$@"
}
string=a__b_+c
eval "array=($(split "$string" '[_+]+'))"
The zshshell memiliki builtin dukungan untuk ekspresi Perl-kompatibel reguler (di-nya zsh/pcremodul), tetapi menggunakannya untuk membagi string, meskipun mungkin relatif rumit.
shellyang Anda gunakan, denganbashyang dapat Anda lakukanIFS='_' read -a array <<< "${string}"