384 votes

Que signifie $@ dans un script shell ?

Que signifie un signe dollar suivi d'un arobase (@) dans un script shell ?

Par exemple :

umbrella_corp_options $@

5 votes

1 votes

427voto

Har Points 508

$@ est tout les paramètres passés au script.

Par exemple, si vous appelez ./someScript.sh foo bar alors $@ sera égal à foo bar.

Si vous faites :

./someScript.sh foo bar

et ensuite à l'intérieur de someScript.sh référence :

umbrella_corp_options "$@"

cela sera passé à umbrella_corp_options avec chaque paramètre individuel enclos dans des guillemets doubles, permettant de prendre des paramètres avec des espaces vides de l'appelant et de les transmettre.

3 votes

Que contiendrait $@ si j'exécutais someScript.sh foo bar "boo far" ?

2 votes

11 votes

$@ est spécial s'il est écrit entre guillemets. Ensuite, cela donnera une liste de valeurs entre guillemets, dans votre cas, trusktr, dans les trois arguments "foo", "bar" et "boo far".

214voto

Alfe Points 12023

$@ est presque la même que $*, signifiant tous deux "tous les arguments de la ligne de commande". Ils sont souvent utilisés pour simplement transmettre tous les arguments à un autre programme (formant ainsi une enveloppe autour de ce programme).

La différence entre les deux syntaxes apparaît lorsque vous avez un argument avec des espaces (par exemple) et que vous mettez $@ entre guillemets doubles :

wrappedProgram "$@"
# ^^^ ceci est correct et transmettra tous les arguments de la manière
#     dont nous les avons reçus, c'est-à-dire en plusieurs arguments,
#     chacun d'eux contenant tous les espaces et autres caractères laids qu'ils ont.
wrappedProgram "$*"
# ^^^ cela transmettra exactement un argument, contenant tous
#     les arguments d'origine, séparés par des espaces simples.
wrappedProgram $*
# ^^^ ceci joindra également tous les arguments par des espaces simples et
#     divisera ensuite la chaîne comme le fait le shell sur la ligne de commande,
#     ce qui divisera un argument contenant des espaces en
#     plusieurs arguments.

Exemple : Appeler

wrapper "un deux    trois" quatre cinq "six sept"

résultera en :

"$@": wrappedProgram "un deux    trois" quatre cinq "six sept"
"$*": wrappedProgram "un deux    trois quatre cinq six sept"
                             ^^^^ Ces espaces font partie du premier
                                  argument et ne sont pas modifiés.
$*:   wrappedProgram un deux trois quatre cinq six sept

4 votes

Ils ne sont pas les mêmes, et la page de manuel est claire sur les effets secondaires de $ * en utilisant IFS - qui n'est pas nécessairement un espace. (S'ils étaient les mêmes, il n'y aurait aucun intérêt, hormis peut-être la compatibilité, à les offrir tous les deux.)

12 votes

Non, ce n'est pas le cas. Et je l'ai dit deux lignes plus bas: "La différence entre les deux ..." Pour obtenir des phrases courtes et améliorer la lisibilité, le lecteur doit lire plus d'une phrase avant de donner un verdict :-/

4 votes

Alfe, l'insertion de ce seul mot "presque" par Christoffer a fait toute la différence, sans sacrifier la concision ou la lisibilité. En fait, j'ai voté pour cette réponse (par opposition à celle acceptée) précisément en raison de cet accent subtil sur la différence... - avant de réaliser que c'était presque contre votre gré! ;)

72voto

Sameer Duwal Points 461

Voici les arguments de ligne de commande où :

$@ = stocke tous les arguments dans une liste de chaînes
$* = stocke tous les arguments sous forme d'une seule chaîne
$# = stocke le nombre d'arguments

0 votes

(L'erreur ci-dessus mentionnée par @iruvar a été corrigée.)

3 votes

Qu'est-ce que "liste" dans ce contexte?

2 votes

"$@" n'est en fait pas une liste de chaînes de caractères, mais une liste d'arguments.

19voto

Luis Lavaire Points 158

Sens.

En bref, $@ s'étend aux arguments transmis par l'appelant à une fonction ou à un script. Son sens est dépendant du contexte : À l'intérieur d'une fonction, il s'étend aux arguments transmis à cette fonction. S'il est utilisé dans un script (en dehors d'une fonction), il s'étend aux arguments transmis à ce script.

$ cat my-script
#! /bin/sh
echo "$@"

$ ./my-script "Salut!"
Salut!

$ put () { echo "$@"; }
$ put "Salut!"
Salut!

* Remarque : Fractionnement des mots.

L'interpréteur de commandes divise les jetons en fonction du contenu de la variable d'environnement IFS. Sa valeur par défaut est \t\n ; c.-à-d., espace blanc, tabulation et nouvelle ligne. En étendant "$@", vous obtenez une copie intacte des arguments transmis. En étendant $@, cela peut ne pas être le cas. Plus précisément, tout argument contenant des caractères présents dans IFS peut être divisé en deux ou plusieurs arguments ou être tronqué.

Ainsi, la plupart du temps, ce que vous voudrez utiliser est "$@", pas $@.

18voto

glglgl Points 35668

L'utilisation d'un pur $@ signifie dans la plupart des cas "blesser le programmeur autant que possible", car dans la plupart des cas cela conduit à des problèmes avec la séparation des mots et avec les espaces et d'autres caractères dans les arguments.

Dans (deviné) 99% des cas, il est nécessaire de l'encadrer de " : "$@" est ce qui peut être utilisé pour itérer de manière fiable sur les arguments.

for a in "$@"; do something_with "$a"; done

5 votes

Votre ligne peut être écrite comme: pour a; faire quelque_chose_avec "$a"; fini ;-)

1 votes

@Alfe Je sais; je l'avais juste oublié. Pensez-y comme pour a dans start_token "$@" end_token; faire quelque_chose_avec "$a"; fait :-)

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