Je tente d'écrire un achèvement bash pour la première fois, et je suis un peu confus quant aux deux façons de déréférencer les tableaux bash ( ${array[@]}
et ${array[*]}
).
Voici le morceau de code pertinent (cela fonctionne, au fait, mais j'aimerais mieux le comprendre):
_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 documentation de bash dit :
Tout élément d'un tableau peut être référencé en utilisant $ {name [indice]}. Les accolades sont nécessaires pour éviter les conflits avec les opérateurs d'extension de nom de fichier du shell. Si l'indice est «@» ou «*», le mot s'étend à tous les membres du nom du tableau. Ces indices ne diffèrent que lorsque le mot apparaît entre guillemets. Si le mot est entre guillemets, $ {name [*]} se développe en un seul mot avec la valeur de chaque membre du tableau séparée par le premier caractère de la variable IFS, et $ {name [@]} développe chaque élément du nom à un mot séparé.
Maintenant, je pense que je comprends que cela compgen -W
attend une chaîne contenant une liste de mots d'alternatives possibles, mais dans ce contexte, je ne comprends pas ce que signifie "$ {name [@]} étend chaque élément de nom à un mot séparé".
Longue histoire courte: ${array[*]}
fonctionne; ${array[@]}
pas. Je voudrais savoir pourquoi et je voudrais mieux comprendre en quoi consiste exactement ${array[@]}
.
la source
Votre titre pose des questions sur le
${array[@]}
versus,${array[*]}
mais ensuite vous demandez sur le$array[*]
versus,$array[@]
ce qui est un peu déroutant. Je répondrai aux deux:Lorsque vous citez une variable de tableau et que vous l'utilisez
@
comme indice, chaque élément du tableau est étendu à son contenu complet, quel que soit l'espace (en fait, l'un des$IFS
) qui peut être présent dans ce contenu. Lorsque vous utilisez l'astérisque (*
) comme indice (qu'il soit cité ou non), il peut s'étendre au nouveau contenu créé en fractionnant le contenu de chaque élément du tableau en$IFS
.Voici l'exemple de script:
#!/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
Et voici sa sortie:
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'
Personnellement, je veux généralement
"${myarray[@]}"
. Maintenant, pour répondre à la deuxième partie de votre question,${array[@]}
contre$array[@]
.Citant les documents bash, que vous avez cités:
$ myarray= $ myarray[0]="one" $ myarray[1]="two" $ echo ${myarray[@]} one two
Mais, lorsque vous le faites
$myarray[@]
, le signe dollar est étroitement liémyarray
, il est donc évalué avant le[@]
. Par exemple:$ ls $myarray[@] ls: cannot access one[@]: No such file or directory
Mais, comme indiqué dans la documentation, les crochets sont pour l'expansion du nom de fichier, alors essayons ceci:
$ touch one@ $ ls $myarray[@] one@
Maintenant, nous pouvons voir que l'expansion du nom de fichier s'est produite après l'
$myarray
expansion.Et une note de plus,
$myarray
sans indice, se développe jusqu'à la première valeur du tableau:$ myarray[0]="one four" $ echo $myarray[5] one four[5]
la source
IFS
la sortie affecte différemment la sortie en fonction de@
vs*
et entre cité et non.${array[*]}
ou${array[@]}
. Le manque d'appareils orthopédiques était simplement de la négligence. Au-delà de cela, pouvez-vous expliquer ce qui${array[*]}
se développerait dans lacompgen
commande? Autrement dit, dans ce contexte, que signifie développer le tableau dans chacun de ses éléments séparément?${array[@]}
c'est généralement la voie à suivre. Ce que j'essaie de comprendre, c'est pourquoi dans ce cas ne${array[*]}
fonctionne que.