Différence entre $@, $*, "$@" et "$*"
Dans un script shell, il existe 2 variables pour accéder aux paramètres de la commande (aussi nommées argv
dans pas mal d’autres langages): $*
et $@
.
$*
est une variable ce qu’il y a de plus normale et ne diffère pas d’une autre variable. Cependant, le comportement des variables diffère en fonction du shell, notamment sur zsh (j’y reviens après).$@
est une variable au comportement différent entre les shells.
Sur bash, il n’y a aucune différence entre $*
et $@
. Par contre, sur ksh et zsh, $@
représente un tableau d’arguments. Il faut savoir que sur bash, utiliser une variable sans guillemet revient à créer autant d’arguments qu’il y a de mots. Les mots sont séparés en fonction des caractères dans $IFS
(la variable contient par défaut : espace, tabulation et saut de ligne). C’est pour cela qu’il est conseillé d’entourer ces variables de guillemets doubles.
Un petit exemple pour comprendre :).
a='a b c'
for v in $a ; do
echo $v
done
> a
> b
> c
Le résultat est 3 lignes pour 1 paramètre, la chaîne 'a b c'
contenant des espaces s’est fait couper. Ce n’est pas le cas pour zsh qui ne fait pas cette césure (raison historique, j’y reviens à la fin).
Maintenant il reste "$*"
et "$@"
qui ne diffèrent pas entre les shells.
"$*"
correspond à une seule chaîne, tout est géré en un seul bloc."$@"
représente les paramètres réels. C’est identique à$@
avec ksh et zsh.
Démonstration
# test.sh
for v in XXX ; do
echo $v
done
Le code ci-dessus est utilisé avec ./test.s 'a b' c
et pour lequel XXX
est remplacé par une des 4 variables précédemment citées.
XXX | bash | ksh | zsh |
---|---|---|---|
$* |
a b c |
a b c |
a b c |
$@ |
a b c |
a b c |
a b c |
"$*" |
a b c | a b c | a b c |
"$@" |
a b c |
a b c |
a b c |
Pour que zsh boucle sur des mots, il faut ajouter un flag à la variable (${=*}
ou $=*
), comme ci-dessous.
a='a b c';
for v in ${=a} ; do
echo $v
done