Bourne / POSIX benzeri mermilerin split + glob operatörü vardır ve liste bağlamında bir parametre genişletmesi ( $var
, $-
...), komut ikamesi ( $(...)
) veya aritmetik genişletme ( $((...))
) bıraktığınızda çağrılır .
Aslında, for name in ${array[@]}
yerine bunu yanlışlıkla başlattınız for name in "${array[@]}"
. (Aslında, bu operatörü yanlışlıkla çağırmanın birçok hatanın ve güvenlik açıklarının kaynağı olduğuna dikkat etmelisiniz ).
Bu operatör $IFS
özel parametreyle (hangi karakterlerin bölüneceğini söylemek için (boşluk, sekme ve yeni satırın orada özel bir işlem aldığını unutmayın)) ve parçayı -f
devre dışı bırakma ( set -f
) veya etkinleştirme ( set +f
) seçeneğiyle yapılandırılır glob
.
Ayrıca, S
in $IFS
orijinal $IFS
olarak Separator için (geldiği Bourne kabuğunda ) iken, POSIX kabuklarında, karakterlerin sınırlayıcı veya sonlandırıcı$IFS
olarak görülmesi gerektiğini unutmayın (bir örnek için aşağıya bakın).
Bölmek için _
:
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.
Ayırıcı ve ayırıcı arasındaki farkı görmek için şunu deneyin:
string='var1_var2_'
Bu onu sadece var1
ve var2
sadece ayıracaktır (ekstra boş eleman yok).
Dolayısıyla, JavaScript'lere benzer hale getirmek için split()
ek bir adıma ihtiyacınız olacak:
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
(boş bir bölme olacağını not $string
içine 1 (değil 0 JavaScript sitesi gibi güvenilir) eleman split()
).
Özel tedaviler sekmesini, alanı ve yeni satır alımını görmek için karşılaştırın:
IFS=' '; string=' var1 var2 '
(nereden alırsınız var1
ve var2
)
IFS='_'; string='_var1__var2__'
Alacağınız burada: ''
, var1
, ''
, var2
, ''
.
Not o zsh
kabuk yapar değil örtülü böyle o bölünmüş + glob operatörü çağırmak içinde olmadıkça sh
veya ksh
öykünme. Orada, onu açıkça çağırmalısınız. $=string
bölünmüş parça $~string
için, glob kısmı için ( $=~string
her ikisi için) ve ayrıca ayırıcıyı belirtebileceğiniz bir bölme operatörü vardır:
array=(${(s:_:)string})
veya boş elemanları korumak için:
array=("${(@s:_:)string}")
Orada unutmayın s
içindir bölünme değil, sınırlayan ile (aynı zamanda $IFS
, bilinen bir POSIX uyumsuzluk zsh
). split()
Boş bir dizenin 0 (1 değil) öğesine bölünmesi JavaScript'ten farklıdır .
İle dikkate değer bir fark $IFS
-splitting olmasıdır ${(s:abc:)string}
üzerinde böler abc
ile birlikte, dize IFS=abc
, bu konuda ayıracaka
, b
ya da c
.
İle zsh
ve ksh93
, uzay, sekme veya satır almalarını özel tedavi bunları iki katına çıkarılabilir $IFS
.
Tarihi bir not olarak, Bourne kabuğu (ata veya modern POSIX kabukları) her zaman boş unsurları soydu. Ayrıca, $ @ öğesinin varsayılan olmayan değerlerle bölünmesi ve genişletilmesi ile ilgili bir dizi hata vardı.$IFS
. Örneğin IFS=_; set -f; set -- $@
, eşdeğer değildir IFS=_; set -f; set -- $1 $2 $3...
.
Normal ifadelerde bölme
Şimdi JavaScript'lere daha yakın bir şey için split()
düzenli ifadelere ayrılabilen için harici yardımcı programlara güvenmeniz gerekir.
POSIX araç göğsünde, genişletilmiş düzenli ifadelere bölünebilen awk
bir split
operatör vardır (bunlar, JavaScript tarafından desteklenen Perl benzeri normal ifadelerin bir veya daha fazla alt kümesidir).
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" '[_+]+'))"
zsh
Kabuk Perl uyumlu düzenli (onun içinde ifade desteği yerleşik vardır zsh/pcre
nispeten hantal mümkün olsa da, modül), ancak bir dize bölmek için kullanıyor.
shell
kullanıyorsun,bash
yapabilirsinIFS='_' read -a array <<< "${string}"