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 $IFS
parameter khusus (untuk memberi tahu karakter apa yang harus dipisah (meskipun berhati-hatilah bahwa ruang, tab, dan baris baru menerima perlakuan khusus di sana)) dan -f
opsi untuk menonaktifkan ( set -f
) atau mengaktifkan ( set +f
) glob
bagian.
Perhatikan juga bahwa sementara S
in $IFS
awalnya (dalam cangkang Bourne dari mana $IFS
) dari untuk Separator, dalam cangkang POSIX, karakter dalam $IFS
seharusnya 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 var1
dan var2
hanya (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 $string
menjadi 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 var1
dan var2
) dengan
IFS='_'; string='_var1__var2__'
di mana Anda mendapatkan: ''
, var1
, ''
, var2
, ''
.
Perhatikan bahwa zsh
shell tidak memanggil operator glob + split yang secara implisit seperti itu kecuali dalam sh
atau ksh
emulasi. Di sana, Anda harus memohonnya dengan jelas. $=string
untuk bagian split, $~string
untuk bagian glob ( $=~string
untuk 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 s
adalah 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 abc
string, sedangkan dengan IFS=abc
, yang akan terpecah a
, b
atau c
.
Dengan zsh
dan 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, awk
memiliki split
operator 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 zsh
shell memiliki builtin dukungan untuk ekspresi Perl-kompatibel reguler (di-nya zsh/pcre
modul), tetapi menggunakannya untuk membagi string, meskipun mungkin relatif rumit.
shell
yang Anda gunakan, denganbash
yang dapat Anda lakukanIFS='_' read -a array <<< "${string}"