Dans de nombreuses SO questions et tutoriels bash, je vois que je peux accéder aux arguments de ligne de commande dans les scripts bash de deux manières:
$ ~ >cat testargs.sh
#!/bin/bash
echo "you passed me" $*
echo "you passed me" $@
Ce qui résulte en:
$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2
Quelle est la différence entre $*
et $@
?
Quand utiliser le premier et quand utiliser le second?
La différence apparaît lorsque les paramètres spéciaux sont cités. Permettez-moi d'illustrer les différences:
$ set -- "arg 1" "arg 2" "arg 3"
$ for Word in $*; do echo "$Word"; done
arg
1
arg
2
arg
3
$ for Word in $@; do echo "$Word"; done
arg
1
arg
2
arg
3
$ for Word in "$*"; do echo "$Word"; done
arg 1 arg 2 arg 3
$ for Word in "$@"; do echo "$Word"; done
arg 1
arg 2
arg 3
un autre exemple sur l'importance de citer: notez qu'il y a 2 espaces entre "arg" et le nombre, mais si je ne cite pas $ Word:
$ for Word in "$@"; do echo $Word; done
arg 1
arg 2
arg 3
et dans bash, "$@"
est la liste "par défaut" sur laquelle itérer:
$ for Word; do echo "$Word"; done
arg 1
arg 2
arg 3
Un tableau récapitulatif pratique du site Wiki Bash Hackers :
où c
dans la troisième ligne est le premier caractère de $IFS
, le séparateur de champs internes, une variable shell.
Si les arguments doivent être stockés dans une variable de script et que les arguments doivent contenir des espaces, je recommande vivement d'utiliser un "$*"
astuce avec le séparateur de champ interne $IFS
réglé sur tab .
$ *
Se développe jusqu'aux paramètres de position, en commençant par un. Lorsque le développement se produit entre guillemets doubles, il se développe en un seul mot avec la valeur de chaque paramètre séparé par le premier caractère de la variable spéciale IFS. Autrement dit, "$ *" équivaut à "$ 1c $ 2c ...", où c est le premier caractère de la valeur de la variable IFS. Si IFS n'est pas défini, les paramètres sont séparés par des espaces. Si IFS est null, les paramètres sont joints sans séparateurs intermédiaires.
$ @
Se développe jusqu'aux paramètres de position, en commençant par un. Lorsque le développement se produit entre guillemets doubles, chaque paramètre se développe dans un mot distinct. C'est-à-dire que "$ @" équivaut à "$ 1" "$ 2" ... Si le développement entre guillemets doubles se produit dans un mot, le développement du premier paramètre est joint au début du mot d'origine, et le développement du dernier paramètre est joint à la dernière partie du mot d'origine. Quand il n'y a pas de paramètre de position, "$ @" et $ @ sont étendus à rien (c'est-à-dire qu'ils sont supprimés).
Source: Bash man
$ @ est identique à $ *, mais chaque paramètre est une chaîne entre guillemets, c'est-à-dire que les paramètres sont transmis tels quels, sans interprétation ni développement. Cela signifie, entre autres choses, que chaque paramètre de la liste d'arguments est considéré comme un mot distinct.
Bien sûr, "$ @" devrait être cité.
Cet exemple peut mettre en évidence les différences entre "at" et "asterix" pendant que nous les utilisons. J'ai déclaré deux tableaux "fruits" et "légumes"
fruits=(Apple pear plumm Peach melon)
vegetables=(carrot tomato cucumber potatoe onion)
printf "Fruits:\t%s\n" "${fruits[*]}"
printf "Fruits:\t%s\n" "${fruits[@]}"
echo + --------------------------------------------- +
printf "Vegetables:\t%s\n" "${vegetables[*]}"
printf "Vegetables:\t%s\n" "${vegetables[@]}"
Voir le résultat suivant le code ci-dessus:
Fruits: Apple pear plumm Peach melon
Fruits: Apple
Fruits: pear
Fruits: plumm
Fruits: Peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion