Os shells Bourne / POSIX têm um operador split + glob e é chamado toda vez que você deixa uma expansão de parâmetro ( $var, $-...), substituição de comando ( $(...)) ou expansão aritmética ( $((...))) sem aspas no contexto da lista.
Na verdade, você invocado por engano quando você fez for name in ${array[@]}em vez de for name in "${array[@]}". (Na verdade, você deve se lembrar de que invocar esse operador assim por engano é fonte de muitos bugs e vulnerabilidades de segurança ).
Esse operador está configurado com o $IFSparâmetro especial (para informar em quais caracteres dividir (embora tenha cuidado com o espaço, a guia e a nova linha receberem um tratamento especial)) e a -fopção de desativar ( set -f) ou ativar ( set +f) a globpeça.
Observe também que, enquanto o Sin $IFSfoi originalmente (no shell Bourne de onde $IFSvem) para Separator, nos shells POSIX, os caracteres em $IFSdevem ser vistos como delimitadores ou terminadores (veja um exemplo abaixo).
Então, para dividir _:
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.
Para ver a distinção entre separador e delimitador , tente:
string='var1_var2_'
Isso o dividirá em var1e var2somente (nenhum elemento extra vazio).
Portanto, para torná-lo semelhante ao JavaScript split(), você precisará de uma etapa extra:
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
(observe que ele dividiria um elemento vazio $stringem 1 (não 0 ), como o JavaScript split()).
Para ver a guia de tratamentos especiais, o espaço e a nova linha, compare:
IFS=' '; string=' var1 var2 '
(de onde você chega var1e var2) com
IFS='_'; string='_var1__var2__'
onde você começa: '', var1, '', var2, ''.
Observe que o zshshell não invoca esse operador split + glob implicitamente assim, a menos que seja dentro shou kshemulado. Lá, você deve invocá-lo explicitamente. $=stringpara a parte dividida, $~stringpara a parte global ( $=~stringpara ambos) e também possui um operador de divisão onde é possível especificar o separador:
array=(${(s:_:)string})
ou para preservar os elementos vazios:
array=("${(@s:_:)string}")
Note-se que não sé para a divisão , não delimitando (também com $IFS, um conhecido POSIX não conformidade do zsh). É diferente do JavaScript, split()pois uma string vazia é dividida em 0 (não 1) elemento.
Uma diferença notável com $IFS-splitting é que se ${(s:abc:)string}divide na abcstring, enquanto com IFS=abc, que se dividiria em a, bou c.
Com zshe ksh93, o tratamento especial que o espaço, a guia ou a nova linha recebe pode ser removido dobrando-os $IFS.
Como uma nota histórica, a concha Bourne (o ancestral ou conchas POSIX modernas) sempre retirava os elementos vazios. Ele também teve vários bugs relacionados à divisão e expansão de $ @ com valores não padrão de $IFS. Por exemplo IFS=_; set -f; set -- $@, não seria equivalente a IFS=_; set -f; set -- $1 $2 $3....
Divisão em regexps
Agora, para algo mais próximo do JavaScript split()que possa ser dividido em expressões regulares, você precisará confiar em utilitários externos.
No baú da ferramenta POSIX, awkexiste um splitoperador que pode ser dividido em expressões regulares estendidas (essas são mais ou menos um subconjunto das expressões regulares do tipo Perl suportadas pelo 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" '[_+]+'))"
O zshshell possui suporte interno para expressões regulares compatíveis com Perl (em seu zsh/pcremódulo), mas usá-lo para dividir uma string, embora possível seja relativamente complicado.
shellvocê está usando, combashque você pode fazerIFS='_' read -a array <<< "${string}"