375 votes

Accès aux arguments de la ligne de commande bash $@ vs $*

Dans de nombreuses questions SO 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 "vous m'avez passé" $*
echo "vous m'avez passé" $@

Ce qui donne :

$ ~> bash testargs.sh arg1 arg2
vous m'avez passé arg1 arg2
vous m'avez passé arg1 arg2

Quelle est la différence entre $* et $@?
Quand devrait-on utiliser le premier et quand devrait-on utiliser le second?

1 votes

Regardez cette réponse : stackoverflow.com/a/842325/671366

0 votes

L'analyse statique dans IntelliJ considère echo "something $@" comme une erreur.

489voto

glenn jackman Points 69748

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 la citation: notez qu'il y a 2 espaces entre "arg" et le numéro, mais si je n'entoure pas $word de guillemets:

$ 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

75 votes

+1 J'ai toujours pensé que ce concept était mieux illustré par un exemple simple, ce qui manque complètement dans le manuel de Bash.

5 votes

Existe-t-il un cas d'utilisation possible lorsque $* ou "$*" peut être requis, et que le but ne peut pas être servi par $@ ou "$@"?

0 votes

Aussi, y a-t-il une différence entre ${arrayname[*]} vs ${arrayname[@]}?

354voto

Serge Stroobandt Points 525

Un joli tableau pratique d'aperçu de Bash Hackers Wiki:

Syntaxe

Résultat effectif

$*

$1 $2 $3 … ${N}

$@

$1 $2 $3 … ${N}

"$*"

"$1c$2c$3c…c${N}"

"$@"

"$1" "$2" "$3" … "${N}"

c dans la troisième rangée est le premier caractère de $IFS, le Séparateur de champ d'entrée, une variable d'environnement.

Si les arguments doivent être stockés, chargez-les dans une variable tableau.

48voto

Muffo Points 598

$*

Se développe pour les paramètres positionnels, en commençant par un. Lorsque l'expansion se produit à l'intérieur de guillemets doubles, elle se développe en un seul mot avec la valeur de chaque paramètre séparée par le premier caractère de la variable spéciale IFS. Autrement dit, "$*" est équivalent à "$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 nul, les paramètres sont joints sans séparateurs intermédiaires.

$@

Se développe pour les paramètres positionnels, en commençant par un. Lorsque l'expansion se produit à l'intérieur de guillemets doubles, chaque paramètre se développe en un mot séparé. Autrement dit, "$@" est équivalent à "$1" "$2" ... Si l'expansion entre guillemets doubles se produit à l'intérieur d'un mot, l'expansion du premier paramètre est jointe avec la partie initiale du mot original, et l'expansion du dernier paramètre est jointe avec la dernière partie du mot original. Lorsqu'il n'y a pas de paramètres positionnels, "$@" et $@ se développent en rien (c'est-à-dire, ils sont supprimés).

Source: Manuel de Bash

20voto

rkosegi Points 3657

$@ est identique à $*, mais chaque paramètre est une chaîne de caractères entre guillemets, c'est-à-dire que les paramètres sont transmis intacts, sans interprétation ni expansion. Cela signifie, entre autres, que chaque paramètre dans la liste d'arguments est considéré comme un mot séparé.

Bien sûr, "$@" doit être entre guillemets.

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST

3voto

stefansson Points 161

Cet exemple peut mettre en évidence la différence entre "at" et "asterix" lorsque nous les utilisons. J'ai déclaré deux tableaux "fruits" et "légumes".

fruits=(pomme poire prune pêche melon)            
légumes=(carotte tomate concombre pomme de terre oignon)

printf "Fruits:\t%s\n" "${fruits[*]}"            
printf "Fruits:\t%s\n" "${fruits[@]}"            
echo + --------------------------------------------- +      
printf "Légumes:\t%s\n" "${légumes[*]}"    
printf "Légumes:\t%s\n" "${légumes[@]}"    

Voici le résultat du code ci-dessus:

Fruits: pomme poire prune pêche melon
Fruits: pomme
Fruits: poire
Fruits: prune
Fruits: pêche
Fruits: melon
+ --------------------------------------------- +
Légumes: carotte tomate concombre pomme de terre oignon
Légumes: carotte
Légumes: tomate
Légumes: concombre
Légumes: pomme de terre
Légumes: oignon

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X