O problema é o seguinte (Aqui não uso find
pois não suporta curinga de asterisco duplo **
):
$ FILES=(foo/**/*.suffix bar/**/*.suffix2)
$ grep baz "${FILES[@]}" # works
# I use this to create one local var with local in one function
$ SUBFILES="${FILES[@]}"
$ grep baz "${SUBFILES[@]}" # doesn't work
Eu costumava od
verificá-los, mas eles são iguais, pelo menos têm o mesmo número de "\n" e o mesmo comprimento (não verifiquei caractere por caractere. Mas, à primeira vista, eles são iguais).
$ echo ${SUBFILES[@]} | od -c
$ echo ${FILES[@]} | od -c
Por que a atribuição de variáveis não cria um objeto que ainda funcione grep
?
Você está certo,
b="${a[@]}"
não cria um array no Bash. Sem os parênteses, isso é uma atribuição escalar, independentemente do que há no lado direito. Então, mesmo que você tenha usado a@
indexação para pedir todos os itens do array separadamente, a atribuição os força a uma única string. O significadob="${a[@]}"
é bem parecido,b="${a[*]}"
exceto que ele sempre usa um espaço como um joiner, em vez do primeiro caractere de$IFS
.Por exemplo
Para obter um array, você precisa adicionar os parênteses, ou seja,
b=( "${a[@]}" )
copiaria um array simples como o que você tem. Eu digo "simples", já que índices de array podem ser não contíguos, e a expansão ali perderia os índices, com a atribuição criando novos, contíguos, começando de0
.Se você quiser uma cópia que mantenha os índices, é provavelmente mais seguro usar apenas um loop. Em geral, as variáveis também têm atributos como os atributos export e integer, e você terá que redefini-los manualmente também. Não há uma maneira simples e direta de copiar uma variável por completo.
Há uma
"${var@A}"
expansão em versões mais recentes do Bash que fornece odeclare
comando para recriar a variável, mas ela contém o nome original, então não pode ser usada imediatamente para cópia. Suponho que você poderia fazer algo assim para copiard
paraf
......mas eu teria cuidado em fazer isso na vida real e, em qualquer caso, isso requer levar em conta os atributos da variável original. Por exemplo, um array de inteiros
g
imprimiria comodeclare -ai g=...
.Note que
echo
une os argumentos que obtém com espaços, entãoecho ${a[@]}
ouecho "${a[@]}"
esconde onde a separação entre os itens do array realmente está. E quando a atribuição escalar une com espaços, eecho
une com espaços, o resultado é que a saída é a mesma em ambos os casos.Isso é
echo
muito ruim para olhar coisas como essa. É melhor usar egprintf
aqui, eg isso deixa mais claro queb
é apenas um único elemento.Ou use
typeset -p
/declare -p
.Mesmo no zsh, onde
$a
ele é expandido como uma matriz (com itens distintos separados), eleb=$a
ainda se junta a uma string, então você precisa saber que tipo de variável está manipulando. (b=$a[@]
é o mesmo, e o zsh usa o primeiro caractere deIFS
para@
e*
, uma pequena diferença do Bash.)As atribuições de matriz em
bash
são escritasNo seu caso,
Isso atribuiria todos os elementos do
FILES
array ao arraySUBFILES
.Com
SUBFILES="${FILES[@]}"
você atribui uma única string à variávelSUBFILES
. Essa string compreenderá os elementos deFILES
separados por espaços simples.Veja também Existem convenções de nomenclatura para variáveis em scripts de shell?