Оболочки типа Bourne / POSIX имеют оператор split + glob, и он вызывается каждый раз, когда вы оставляете в кавычках раскрытие параметров ( $var, $-...), команду substitution ( $(...)) или арифметическое расширение ( $((...))) без кавычек.
На самом деле, вы вызвали это по ошибке, когда вы сделали for name in ${array[@]}вместо for name in "${array[@]}". (На самом деле, вы должны помнить, что такой ошибочный вызов оператора является источником многих ошибок и уязвимостей в безопасности ).
Этот оператор настроен со $IFSспециальным параметром (чтобы указать, на какие символы разбивать (хотя имейте в виду, что пробел, табуляция и новая строка там получают специальную обработку)) и -fвозможностью отключить ( set -f) или включить ( set +f) globчасть.
Также обратите внимание, что в то время как Sin $IFSизначально был (в оболочке Bourne, откуда $IFSпроисходит) для Separator, в оболочках POSIX символы in $IFSлучше рассматривать как разделители или терминаторы (см. Пример ниже).
Итак, разделить на _:
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.
Чтобы увидеть различие между разделителем и разделителем , попробуйте:
string='var1_var2_'
Это разделит его на var1и var2только (без дополнительного пустого элемента).
Итак, чтобы сделать его похожим на JavaScript split(), вам понадобится дополнительный шаг:
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
(обратите внимание, что он разделит пустой элемент $stringна 1 (не 0 ), как в JavaScript split()).
Чтобы увидеть вкладку специальных процедур, пробел и перевод новой строки, сравните:
IFS=' '; string=' var1 var2 '
(где вы получаете var1и var2) с
IFS='_'; string='_var1__var2__'
где вы получите: '', var1, '', var2, ''.
Обратите внимание, что zshоболочка не вызывает этот оператор split + glob неявным образом, если только в shили kshэмуляция. Там вы должны вызывать это явно. $=stringдля части split, $~stringдля части glob ( $=~stringдля обеих), а также есть оператор split, где вы можете указать разделитель:
array=(${(s:_:)string})
или сохранить пустые элементы:
array=("${(@s:_:)string}")
Обратите внимание, что есть sдля разделения , а не разграничения (также с $IFSизвестным несоответствием POSIX zsh). Он отличается от JavaScript тем, split()что пустая строка разбита на 0 (не 1) элемент.
Заметная разница с $IFS-splitting заключается в том, что она ${(s:abc:)string}разделяется на abcстроку, тогда как с IFS=abc, которая разделяется на a, bили c.
С zshи ksh93, специальная обработка, которую получают пробел, табуляция или перевод строки, может быть удвоена $IFS.
Как историческое примечание, оболочка Bourne (предок или современные оболочки POSIX) всегда очищала пустые элементы. Также было несколько ошибок, связанных с разбиением и расширением $ @ со значениями не по умолчанию $IFS. Например IFS=_; set -f; set -- $@, не будет эквивалентно IFS=_; set -f; set -- $1 $2 $3....
Расщепление по регулярным выражениям
Теперь, для чего-то более похожего на JavaScript, split()который может разбиваться на регулярные выражения, вам нужно полагаться на внешние утилиты.
В сундуке с инструментами POSIX awkесть splitоператор, который может разбивать расширенные регулярные выражения (это более или менее подмножество Perl-подобных регулярных выражений, поддерживаемых 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" '[_+]+'))"
В zshоболочку встроена поддержка регулярных выражений, совместимых с Perl (в ее zsh/pcreмодуле), но использование ее для разделения строки, хотя и возможно, является относительно громоздким.
shellвы используете, с чемbashвы можете сделатьIFS='_' read -a array <<< "${string}"