Estoy intentando escribir una finalización de bash por primera vez, y estoy un poco confundido acerca de las dos formas de desreferenciar matrices de bash ( ${array[@]}y ${array[*]}).
Aquí está el fragmento de código relevante (funciona, por cierto, pero me gustaría entenderlo mejor):
_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} ) )
}
La documentación de bash dice :
Se puede hacer referencia a cualquier elemento de una matriz usando $ {nombre [subíndice]}. Las llaves son necesarias para evitar conflictos con los operadores de expansión de nombre de archivo del shell. Si el subíndice es '@' o '*', la palabra se expande a todos los miembros del nombre de la matriz. Estos subíndices difieren solo cuando la palabra aparece entre comillas dobles. Si la palabra está entre comillas dobles, $ {nombre [*]} se expande a una sola palabra con el valor de cada miembro de la matriz separado por el primer carácter de la variable IFS, y $ {nombre [@]} expande cada elemento del nombre a una palabra separada.
Ahora creo que entiendo que compgen -Wespera una cadena que contenga una lista de palabras de posibles alternativas, pero en este contexto no entiendo qué significa "$ {nombre [@]} expande cada elemento del nombre a una palabra separada".
En pocas palabras: ${array[*]}funciona; ${array[@]}no lo hace. Me gustaría saber por qué, y me gustaría entender mejor en qué se ${array[@]}expande exactamente .
fuente

Tu título pregunta sobre
${array[@]}versus,${array[*]}pero luego preguntas sobre$array[*]versus, lo$array[@]cual es un poco confuso. Responderé a ambos:Cuando cita una variable de matriz y la usa
@como subíndice, cada elemento de la matriz se expande a su contenido completo independientemente del espacio en blanco (en realidad, uno de$IFS) que pueda estar presente dentro de ese contenido. Cuando usa el asterisco (*) como subíndice (independientemente de si está citado o no), puede expandirse a nuevo contenido creado al dividir el contenido de cada elemento de la matriz en$IFS.Aquí está el script de ejemplo:
#!/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'" doneY aquí está su salida:
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'Yo personalmente suelo querer
"${myarray[@]}". Ahora, para responder a la segunda parte de su pregunta,${array[@]}versus$array[@].Citando los documentos de bash, que citó:
$ myarray= $ myarray[0]="one" $ myarray[1]="two" $ echo ${myarray[@]} one twoPero, cuando lo hace
$myarray[@], el signo de dólar está estrechamente vinculado, pormyarraylo que se evalúa antes que el[@]. Por ejemplo:$ ls $myarray[@] ls: cannot access one[@]: No such file or directoryPero, como se indica en la documentación, los corchetes son para la expansión del nombre de archivo, así que intentemos esto:
$ touch one@ $ ls $myarray[@] one@Ahora podemos ver que la expansión del nombre de archivo ocurrió después de la
$myarrayexpansión.Y una nota más,
$myarraysin un subíndice, se expande al primer valor de la matriz:$ myarray[0]="one four" $ echo $myarray[5] one four[5]fuente
IFSafecta la salida de manera diferente según@vs.*y cotizado vs. no cotizado.${array[*]}o${array[@]}. La falta de frenillos fue simplemente un descuido. Más allá de eso, ¿puede explicar en qué${array[*]}se expandiría elcompgencomando? Es decir, en ese contexto, ¿qué significa expandir la matriz en cada uno de sus elementos por separado?${array[@]}suele ser el camino a seguir. Lo que estoy tratando de entender es por qué en este caso solo${array[*]}funciona.