Que signifie $ @ dans un script shell?


Réponses:


263

$@correspond à tous les paramètres passés au script.

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

Si tu fais:

./someScript.sh foo bar

puis someScript.shréférence intérieure :

umbrella_corp_options "$@"

celui-ci sera transmis umbrella_corp_optionsavec chaque paramètre individuel entre guillemets, permettant de prendre des paramètres avec un espace vide de l'appelant et de les transmettre.


1
Que contiendrait $ @ si je le faisais someScript.sh foo bar "boo far"?
— trusktr


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

5
Bien que ce soit généralement le cas, $@ne vient pas nécessairement des paramètres passés au script ... par exemple; set a b "x   y"; printf '(%s)' "$@"sorties(a)(b)(x   y)
— Peter.O

2
J'aime mieux la réponse d'Alfe parce qu'il donne la principale différence entre $@et$*
— donleyp

114

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

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

wrappedProgram "$@"
# ^^^ this is correct and will hand over all arguments in the way
#     we received them, i. e. as several arguments, each of them
#     containing all the spaces and other uglinesses they have.
wrappedProgram "$*"
# ^^^ this will hand over exactly one argument, containing all
#     original arguments, separated by single spaces.
wrappedProgram $*
# ^^^ this will join all arguments by single spaces as well and
#     will then split the string as the shell does on the command
#     line, thus it will split an argument containing spaces into
#     several arguments.

Exemple: appel

wrapper "one two    three" four five "six seven"

aura pour résultat:

"$@": wrappedProgram "one two    three" four five "six seven"
"$*": wrappedProgram "one two    three four five six seven"
                             ^^^^ These spaces are part of the first
                                  argument and are not changed.
$*:   wrappedProgram one two three four five six seven

2
Ce 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, autre que la compatibilité peut-être, à offrir les deux.)
— jørgensen

7
Non ils ne sont pas. Et je l'ai dit deux lignes ci-dessous: "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 rendre un verdict: - /
— Alfe

2
Alfe, l'insertion par Christoffer de ce mot «presque» a fait une sacrée différence, sans sacrifier aucune lacune ni lisibilité. En fait, j'ai voté pour cette réponse (par opposition à celle acceptée) exactement en raison de cette subtile accentuation de la différence ... - avant de réaliser que c'était presque contre votre volonté! ;)
— Sz.

Je pense que ce mot a fait une sacrée différence pour les gens qui ont rendu un verdict juste après avoir lu la première phrase ;-) et cela n'a jamais été contre ma volonté. J'aimerais vraiment écrire aussi pour ces personnes.
— Alfe

Très peu clair. wrappedProgram "$*"-> separated by single spaces.mais dans votre 2ème exemple, ils ne sont pas séparés par des espaces simples.
— Felix Dombek

39

Voici les arguments de ligne de commande où:

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


(L'inexactitude ci-dessus mentionnée par @iruvar a été corrigée.)
— Mateen Ulhaq

13

L'utilisation d'un $@moyen pur dans la plupart des cas "fait mal au programmeur aussi fort que vous le pouvez", car dans la plupart des cas, cela conduit à des problèmes de séparation des mots et d'espaces et autres caractères dans les arguments.

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

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

4
Votre ligne peut être écrite comme suit: pour a; faire quelque chose_avec "$ a"; done ;-)
— Alfe

1
@Alfe je sais; je déteste juste ça. Pensez-y comme for a in start_token "$@" end_token; do something_with "$a"; done:-)
— glglgl

9

À partir du manuel:

@

S'étend aux paramètres de position, en commençant par un. Lorsque l'expansion se produit entre guillemets, chaque paramètre se développe en un mot distinct. Autrement dit, "$ @" équivaut à "$ 1" "$ 2" .... Si le développement entre guillemets doubles se produit dans un mot, le développement du premier paramètre est joint à la partie de début du mot d'origine, et le l'expansion du dernier paramètre est jointe à la dernière partie du mot d'origine. Lorsqu'il n'y a pas de paramètres de position, "$ @" et $ @ s'étendent à rien (c'est-à-dire qu'ils sont supprimés).


1

Sens.

En bref, $@s'étend aux arguments positionnels passés de l'appelant à une fonction ou à un script . Sa signification dépend du contexte : à l'intérieur d'une fonction, elle s'étend aux arguments passés à une telle fonction. S'il est utilisé dans un script (pas dans la portée d'une fonction), il s'étend aux arguments passés à ce script.

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

$ ./my-sh "Hi!"
Hi!
$ put () ( echo "$@" )
$ put "Hi!"
Hi!

Partage de mots.

Maintenant, un autre sujet qui est d'une importance primordiale pour comprendre comment $@se comporte dans le shell est le fractionnement de mots . Le shell divise les jetons en fonction du contenu de la IFSvariable. Sa valeur par défaut est \t\n; c'est-à-dire, espace blanc, tabulation et nouvelle ligne.

L'expansion "$@"vous donne une copie parfaite des arguments passés. Cependant, l'expansion $@ne le sera pas toujours. Plus précisément, si les arguments contiennent des caractères de IFS, ils seront séparés.


La plupart du temps, ce que vous voudrez utiliser ne l'est "$@"pas $@.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.