Resumindo: você deve usar aspas em torno de expansões de array assim, a menos que você queira explicitamente a divisão de campos / palavras. "$@"
expande cada parâmetro posicional para uma palavra separada e, da mesma forma, "${a[@]}"
. Por extensão, isso deve funcionar da mesma maneira para "${a[@]:0:2}"
.
Dito isto, ainda parece uma inconsistência no Bash, e o que você usou deve funcionar no seu caso (já que não há caracteres glob nos valores, e a divisão do campo é feita por IFS
sendo configurada corretamente) .
Tomando o array completo funciona:
$ IFS=$'\n'
$ a=("foo bar" "asdf ghjk")
$ printf "%s\n" ${a[@]}
foo bar
asdf ghjk
Fatiar não funciona para uma matriz, mas funciona para $@
:
$ printf "%s\n" ${a[@]:0:2}
foo bar asdf ghjk
$ set -- "aa bb" "cc dd"
$ printf "%s\n" ${@:1:2}
aa bb
cc dd
Ele funciona em ksh e zsh, o que meio que sublinha que Bash é inconsistente aqui (zsh obviamente teria sua própria sintaxe para o equivalente) :
$ ifs=$'\n' ksh -c 'IFS="$ifs"; a=("foo bar" "asdf ghjk"); printf "%s\n" ${a[@]:0:2}'
foo bar
asdf ghjk
$ ifs=$'\n' zsh -yc 'IFS="$ifs"; a=("foo bar" "asdf ghjk"); printf "%s\n" ${a[@]:0:2}'
foo bar
asdf ghjk
A versão citada também funciona no Bash e é melhor quando você quer apenas os valores como estão, desde que você não precise depender de IFS
. O padrão IFS
funciona bem aqui, mesmo que os elementos da matriz tenham espaços:
$ unset IFS # uses default of $' \t\n'
$ printf "%s\n" "${a[@]:0:2}"
foo bar
asdf ghjk
Parece que o ${a[@]:0:2}
sem aspas une os elementos com espaços, um pouco como o que acontece no Bash em contextos em que a divisão de palavras não acontece (por exemplo, str=${a[@]}
). E então ele tenta dividir o resultado com IFS
, como de costume. Por exemplo. aqui, ele se divide na nova linha no meio do segundo elemento da matriz:
$ IFS=$'\n'
$ a=("foo bar" $'new\nline' "asdf ghjk");
$ printf ":%s\n" ${a[@]:0:3}
:foo bar new
:line asdf ghjk
Como dito acima, você deve usar as aspas em torno de expansões de array na maioria dos casos, embora, ainda assim, alguém assuma que ${a[@]:n:m}
resultaria em várias palavras, assim como ${a[@]}
faz.
O comportamento aqui parece estar presente no Bash 4.4.12(1)-release
e 5.0.0(1)-alpha
. Eu postei um relatório de bug sobre isso.