Cosa significa $ @ in uno script di shell?


Risposte:


243

$@sono tutti i parametri passati allo script.

Ad esempio, se chiami ./someScript.sh foo barallora $@sarà uguale a foo bar.

Se fate:

./someScript.sh foo bar

e poi someScript.shriferimento interno :

umbrella_corp_options "$@"

questo verrà passato a umbrella_corp_optionsogni singolo parametro racchiuso tra virgolette doppie, consentendo di prendere parametri con uno spazio vuoto dal chiamante e trasmetterli.


1
Cosa contiene $ @ se lo facessi someScript.sh foo bar "boo far"?
trusktr,


7
$ @ è speciale se scritto tra virgolette doppie. Quindi si otterrà un elenco di valori tra virgolette, nel tuo caso, trusktr, nei tre argomenti "foo", "bar" e "boo far".
Alfe,

4
Sebbene sia generalmente il caso, $@non proviene necessariamente da parametri passati allo script ... ad esempio; set a b "x   y"; printf '(%s)' "$@"uscite(a)(b)(x   y)
Peter.O

Mi piace meglio la risposta di Alfe perché dà la differenza principale tra $@e$*
donleyp il

106

$@è quasi uguale a $*, entrambi significano "tutti gli argomenti della riga di comando". Sono spesso usati per semplicemente passare tutti gli argomenti a un altro programma (formando così un involucro attorno a quell'altro programma).

La differenza tra le due sintassi si presenta quando si ha un argomento con spazi (ad es.) E si mettono $@tra virgolette:

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.

Esempio: chiamata

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

comporterà:

"$@": 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
Essi sono non la stessa, e la pagina di manuale è chiaro sugli effetti collaterali di $ * utilizzando IFS-il che non è necessariamente lo spazio. (Se fossero uguali, non ci sarebbe alcun punto, se non forse la compatibilità, nell'offrire entrambi.)
jørgensen,

6
No non lo sono. E ho detto due righe qui sotto: "La differenza tra i due ..." Per ottenere frasi brevi e aumentare la leggibilità, il lettore deve leggere più di una frase prima di dare un verdetto: - /
Alfe

2
Comunque, l'inserzione di Christoffer di quell'unica parola "quasi" ha fatto una differenza infernale, senza sacrificare alcuna terseness o leggibilità. In effetti ho votato a favore di questa risposta (al contrario di quella accettata) proprio per quella sottile enfasi della differenza ... - prima di rendermi conto che era quasi contro la tua volontà! ;)
Sz.

Penso che quella parola abbia fatto la differenza per le persone che hanno emesso un verdetto subito dopo aver letto la prima frase ;-) e non è mai stato contro la mia volontà. Mi piacerebbe davvero scrivere anche per queste persone.
Alfe

Molto poco chiaro wrappedProgram "$*"-> separated by single spaces.ma nel tuo secondo esempio non sono separati da spazi singoli.
Felix Dombek,

36

Questi sono gli argomenti della riga di comando in cui:

$@= memorizza tutti gli argomenti in un elenco di stringhe
$*= memorizza tutti gli argomenti come una singola stringa
$#= memorizza il numero di argomenti


(L'inesattezza sopra menzionata da @iruvar è stata corretta.)
Mateen Ulhaq,

13

L'uso di un $@mezzo puro nella maggior parte dei casi "danneggia il programmatore il più forte possibile", perché nella maggior parte dei casi porta a problemi con la separazione delle parole e con spazi e altri caratteri negli argomenti.

Nel (indovinato) 99% di tutti i casi, è necessario racchiuderlo in ": "$@"è ciò che può essere usato per iterare in modo affidabile sugli argomenti.

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

4
La tua riga può essere scritta come: per a; fare qualcosa_con "$ a"; fatto ;-)
Alfe

1
@Alfe lo so; l'ho appena dimenticato. Pensalo come for a in start_token "$@" end_token; do something_with "$a"; done:-)
glglgl

9

Dal manuale:

@

Si espande nei parametri posizionali, a partire da uno. Quando l'espansione avviene tra virgolette doppie, ogni parametro si espande in una parola separata. Ossia, "$ @" equivale a "$ 1" "$ 2" .... Se l'espansione tra virgolette doppie si verifica all'interno di una parola, l'espansione del primo parametro viene unita alla parte iniziale della parola originale e il l'espansione dell'ultimo parametro viene unita all'ultima parte della parola originale. Quando non ci sono parametri posizionali, "$ @" e $ @ si espandono in nulla (cioè vengono rimossi).


1

Senso.

In breve, si $@espande agli argomenti posizionali passati dal chiamante a una funzione o uno script . Il suo significato dipende dal contesto : all'interno di una funzione, si espande agli argomenti passati a tale funzione. Se utilizzato in uno script (non all'interno dell'ambito di una funzione), si espande agli argomenti passati a tale script.

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

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

Suddivisione delle parole.

Ora, un altro argomento di fondamentale importanza quando si comprende come $@si comporta nella shell è la suddivisione delle parole . La shell divide i token in base al contenuto della IFSvariabile. Il suo valore predefinito è \t\n; ovvero spazi bianchi, tabulazione e newline.

L'espansione "$@"ti dà una copia incontaminata degli argomenti passati. Tuttavia, l'espansione $@non sempre. Più specificamente, se gli argomenti contengono caratteri da IFS, verranno divisi.


Il più delle volte ciò che vorrai usare è "$@"no $@.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.