Pages

dimanche 17 février 2013

Différence entre $@, $*, "$@" et "$*"

Après avoir vu l'utilisation de $@ dans un script shell, je me suis demandé la différence avec $*.
Pour rappel, ces variables représentent les arguments de la ligne de commande.

$* est une variable ce qu'il y à 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 basés sur sh (bash,dash,...) et les autres (ksh, zsh).

Sur sh aucune différence entre $@ et $*. Par contre sur ksh/zsh cela représente le `tableau` d'argument. Il faut savoir qu'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 de $IFS (la variable contient : espace, tabulation et saut de ligne). C'est pour ça 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 (raison historique, j'y reviens à la fin).

Maintenant il reste "$*" et "$@" qui ne diffère pas entre les shells.
"$*" correspond à une seul chaîne, tout est gérer en un seul bloc.
"$@" représente les paramètres réel. C'est identique à $@ avec ksh et zsh.

Petit tableau récapitulatif avec le même type de boucle qu'au-dessus et un appel avec deux paramètres.

./test 'a b' c
var/shell sh/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 (${=*}), comme ci-dessous.

$ a='a b c'; for v in ${=a} ; do echo $v ; done

Aucun commentaire: