Powłoki typu Bourne / POSIX mają operator split + glob i jest on wywoływany za każdym razem, gdy nie podaje się wyrażenia parametru ( $var, $-...), podstawienia polecenia ( $(...)) lub rozszerzenia arytmetycznego ( $((...))) w kontekście listy.
Właściwie przywołałeś go przez pomyłkę, kiedy to zrobiłeś for name in ${array[@]}zamiast for name in "${array[@]}". (W rzeczywistości powinieneś wystrzegać się tego, że przywołanie takiego operatora przez pomyłkę jest źródłem wielu błędów i luk w zabezpieczeniach ).
Ten operator jest skonfigurowany z $IFSparametrem specjalnym (aby powiedzieć, na jakie znaki mają się dzielić (choć uważaj, że spacja, tabulator i znak nowej linii są tam specjalnie traktowane)) i -fopcją wyłączenia ( set -f) lub włączenia ( set +f) globczęści.
Zauważ też, że chociaż Sin $IFSbył pierwotnie (w powłoce Bourne'a, skąd $IFSpochodzi) dla Separatora, w powłokach POSIX, znaki w $IFSpowinny być raczej postrzegane jako separatory lub terminatory (patrz przykład poniżej).
Podzielmy się na _:
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.
Aby zobaczyć różnicę między separatorem a separatorem , spróbuj:
string='var1_var2_'
To będzie podzielić ją na var1i var2tylko (bez dodatkowych pusty element).
Aby więc był podobny do skryptów JavaScript split(), potrzebujesz dodatkowego kroku:
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
(zwróć uwagę, że podzieliłby pusty element $stringna 1 (nie 0 ), jak JavaScript split()).
Aby zobaczyć kartę specjalnych zabiegów, spację i znak nowej linii, porównaj:
IFS=' '; string=' var1 var2 '
(skąd bierzesz var1i var2) z
IFS='_'; string='_var1__var2__'
gdzie można uzyskać: '', var1, '', var2, ''.
Zauważ, że zshpowłoka nie wywołuje tego operatora split + glob domyślnie w ten sposób, chyba że w shlub kshemulacji. Tam musisz je bezpośrednio przywołać. $=stringdla części podzielonej, $~stringdla części globalnej ( $=~stringdla obu), a także ma operator podziału, w którym można określić separator:
array=(${(s:_:)string})
lub w celu zachowania pustych elementów:
array=("${(@s:_:)string}")
Należy zauważyć, że nie sjest do rozszczepiania , nie ograniczające (również $IFS, znany POSIX niezgodności z zsh). Różni się od skryptów JavaScript tym, split()że pusty ciąg jest podzielony na element 0 (nie 1).
Godnym Różnica $IFS-splitting jest to, że ${(s:abc:)string}podziały na abcstruny, natomiast z IFS=abc, które podzielone na a, blub c.
Za pomocą zshi ksh93, specjalne traktowanie, które otrzymują spacja, tabulator lub znak nowej linii, można usunąć, podwajając je $IFS.
Historycznie rzecz biorąc, powłoka Bourne'a (przodek lub współczesne pociski POSIX) zawsze usuwała puste elementy. Miał także szereg błędów związanych z dzieleniem i rozszerzaniem $ @ o wartościach innych niż default $IFS. Na przykład IFS=_; set -f; set -- $@nie byłoby równoważne z IFS=_; set -f; set -- $1 $2 $3....
Dzielenie wyrażeń regularnych
Teraz, aby znaleźć coś bliższego JavaScript'owi, split()który może dzielić się na wyrażenia regularne, musisz polegać na zewnętrznych narzędziach.
W skrzynce narzędzi POSIX awkma splitoperator, który może dzielić rozszerzone wyrażenia regularne (są one mniej więcej podzbiorem wyrażeń regularnych podobnych do Perla obsługiwanych przez 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" '[_+]+'))"
zshPowłoka posiada wbudowane wsparcie dla kompatybilnych Perl wyrażeń regularnych (w jego zsh/pcremoduł), ale przy użyciu go podzielić ciąg, choć możliwe jest stosunkowo kłopotliwe.
shellużywasz, zbashczym możesz zrobićIFS='_' read -a array <<< "${string}"