Estou tentando escrever uma conclusão de bash pela primeira vez e estou um pouco confuso sobre as duas maneiras de desreferenciar matrizes de bash ( ${array[@]}
e${array[*]}
).
Aqui está o trecho de código relevante (funciona, a propósito, mas gostaria de entendê-lo melhor):
_switch()
{
local cur perls
local ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew}
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
perls=($ROOT/perls/perl-*)
# remove all but the final part of the name
perls=(${perls[*]##*/})
COMPREPLY=( $( compgen -W "${perls[*]} /usr/bin/perl" -- ${cur} ) )
}
A documentação do bash diz :
Qualquer elemento de um array pode ser referenciado usando $ {name [subscript]}. As chaves são necessárias para evitar conflitos com os operadores de expansão de nome de arquivo do shell. Se o subscrito for '@' ou '*', a palavra se expandirá para todos os membros do nome da matriz. Esses subscritos diferem apenas quando a palavra aparece entre aspas duplas. Se a palavra estiver entre aspas duplas, $ {name [*]} se expande para uma única palavra com o valor de cada membro da matriz separado pelo primeiro caractere da variável IFS, e $ {name [@]} expande cada elemento do nome para uma palavra separada.
Agora acho que entendo que compgen -W
espera uma string contendo uma lista de palavras de alternativas possíveis, mas neste contexto eu não entendo o que "$ {name [@]} expande cada elemento do nome para uma palavra separada" significa.
Resumindo: ${array[*]}
obras; ${array[@]}
não. Eu gostaria de saber por que e de entender melhor o que exatamente se ${array[@]}
expande.
fonte
Seu título pergunta sobre
${array[@]}
versus,${array[*]}
mas você pergunta sobre$array[*]
versus, o$array[@]
que é um pouco confuso. Vou responder a ambos:Quando você cita uma variável de matriz e usa
@
como um subscrito, cada elemento da matriz é expandido para seu conteúdo completo, independentemente do espaço em branco (na verdade, um de$IFS
) que possa estar presente nesse conteúdo. Quando você usa o asterisco (*
) como o subscrito (independentemente de estar entre aspas ou não), ele pode se expandir para um novo conteúdo criado dividindo o conteúdo de cada elemento da matriz em$IFS
.Aqui está o script de exemplo:
#!/bin/sh myarray[0]="one" myarray[1]="two" myarray[3]="three four" echo "with quotes around myarray[*]" for x in "${myarray[*]}"; do echo "ARG[*]: '$x'" done echo "with quotes around myarray[@]" for x in "${myarray[@]}"; do echo "ARG[@]: '$x'" done echo "without quotes around myarray[*]" for x in ${myarray[*]}; do echo "ARG[*]: '$x'" done echo "without quotes around myarray[@]" for x in ${myarray[@]}; do echo "ARG[@]: '$x'" done
E aqui está o resultado:
with quotes around myarray[*] ARG[*]: 'one two three four' with quotes around myarray[@] ARG[@]: 'one' ARG[@]: 'two' ARG[@]: 'three four' without quotes around myarray[*] ARG[*]: 'one' ARG[*]: 'two' ARG[*]: 'three' ARG[*]: 'four' without quotes around myarray[@] ARG[@]: 'one' ARG[@]: 'two' ARG[@]: 'three' ARG[@]: 'four'
Eu pessoalmente geralmente quero
"${myarray[@]}"
. Agora, para responder à segunda parte de sua pergunta,${array[@]}
versus$array[@]
.Citando os documentos do bash, que você citou:
$ myarray= $ myarray[0]="one" $ myarray[1]="two" $ echo ${myarray[@]} one two
Mas, quando você faz isso
$myarray[@]
, o cifrão está fortemente vinculado a,myarray
portanto, é avaliado antes de[@]
. Por exemplo:$ ls $myarray[@] ls: cannot access one[@]: No such file or directory
Mas, conforme observado na documentação, os colchetes são para expansão de nome de arquivo, então vamos tentar isso:
$ touch one@ $ ls $myarray[@] one@
Agora podemos ver que a expansão do nome do arquivo aconteceu após a
$myarray
exapansão.E mais uma nota,
$myarray
sem um subscrito se expande para o primeiro valor da matriz:$ myarray[0]="one four" $ echo $myarray[5] one four[5]
fonte
IFS
afeta a saída de forma diferente dependendo@
vs.*
e citou vs. unquoted.${array[*]}
ou${array[@]}
. A falta de aparelho ortodôntico era simplesmente descuido. Além disso, você pode explicar o que${array[*]}
se expandiria nocompgen
comando? Ou seja, nesse contexto, o que significa expandir a matriz em cada um de seus elementos separadamente?${array[@]}
geralmente é o caminho a seguir. O que estou tentando entender é por que nesse caso só${array[*]}
funciona.