Co oznacza $ @ w skrypcie powłoki?

Odpowiedzi:

242

$@to wszystkie parametry przekazane do skryptu.

Na przykład, jeśli zadzwonisz ./someScript.sh foo barwtedy $@będzie równa foo bar.

Jeśli zrobisz:

./someScript.sh foo bar

a następnie wewnątrz someScript.shodniesienia:

umbrella_corp_options "$@"

zostanie to przekazane umbrella_corp_optionsz każdym parametrem ujętym w podwójne cudzysłowy, umożliwiając pobranie parametrów z pustą spacją od osoby dzwoniącej i przekazanie ich dalej.

Har
źródło
1
Co zawiera $ @, gdybym to zrobił someScript.sh foo bar "boo far"?
trusktr
7
$ @ jest wyjątkowy, jeśli jest napisany w podwójnym cudzysłowie. Doprowadzi to do utworzenia listy cytowanych wartości, w twoim przypadku trusktr, z trzema argumentami „foo”, „bar” i „boo far”.
Alfe,
4
Chociaż jest to zwykle ma miejsce, $@czy niekoniecznie pochodzą z paramaters przekazanych do skryptu ... np; set a b "x   y"; printf '(%s)' "$@"wyniki(a)(b)(x   y)
Peter.O
Bardziej podoba mi się odpowiedź Alfe'a, ponieważ podaje on główną różnicę między $@i$*
donleyp
106

$@jest prawie taki sam jak $*, oba oznaczają „wszystkie argumenty wiersza poleceń”. Często są one używane do przekazywania wszystkich argumentów do innego programu (tworząc w ten sposób opakowanie tego innego programu).

Różnica między dwiema składniami pojawia się, gdy masz argument ze spacjami (np.) I wstawisz $@podwójne cudzysłowy:

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.

Przykład: dzwonienie

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

spowoduje:

"$@": 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
Alfe
źródło
2
Nie są one takie same, a strona podręcznika pokazuje efekty uboczne $ * przy użyciu IFS - co niekoniecznie jest przestrzenią. (Gdyby były takie same, oferowanie obu nie miałoby żadnego innego znaczenia niż zgodność).
jørgensen
6
Nie oni nie są. I tak powiedział dwie linie poniżej: „Różnica między nimi ...” w celu uzyskania krótkich zdań i podnieść czytelność czytelnik ma więcej niż jedno zdanie przed wydaniem wyroku: - /
Alfe
2
Alfe, wstawienie przez Christoffera tego jednego słowa „prawie” zrobiło ogromną różnicę, nie poświęcając żadnej zwięzłości czy czytelności. W rzeczywistości głosowałem za odpowiedzią (w przeciwieństwie do przyjętej) właśnie z powodu tego subtelnego podkreślenia różnicy ... - zanim zdałem sobie sprawę, że było to wbrew twojej woli! ;)
Sz.
Myślę, że to słowo zrobiło ogromną różnicę dla ludzi, którzy wydają werdykt zaraz po przeczytaniu pierwszego zdania ;-) i nigdy nie było wbrew mojej woli. Naprawdę chciałbym pisać także dla tych ludzi.
Alfe
Bardzo niejasne. wrappedProgram "$*"-> separated by single spaces.ale w drugim przykładzie nie są one oddzielone pojedynczymi spacjami.
Felix Dombek
36

Oto argumenty wiersza poleceń, w których:

$@= przechowuje wszystkie argumenty na liście ciągów
$*= przechowuje wszystkie argumenty jako pojedynczy ciąg
$#= przechowuje liczbę argumentów

Sameer Duwal
źródło
(Powyższa niedokładność wspomniana przez @iruvar została naprawiona.)
Mateen Ulhaq
13

Użycie czystych $@środków w większości przypadków „rani programistę tak mocno, jak to możliwe”, ponieważ w większości przypadków prowadzi to do problemów z separacją słów oraz spacjami i innymi znakami w argumentach.

W (przypuszczalnie) 99% wszystkich przypadków wymagane jest zawarcie go w ": "$@"to, co można wykorzystać do rzetelnego iterowania argumentów.

for a in "$@"; do something_with "$a"; done
glglgl
źródło
4
Twój wiersz można zapisać jako: dla; zrób coś z „$ a”; gotowe ;-)
Alfe,
1
@Afe, wiem; po prostu zapomniałem. Pomyśl o tym jako for a in start_token "$@" end_token; do something_with "$a"; done:-)
glglgl
9

Z instrukcji:

@

Rozwija się do parametrów pozycyjnych, zaczynając od jednego. Kiedy rozwinięcie występuje w podwójnych cudzysłowach, każdy parametr rozwija się do osobnego słowa. Oznacza to, że „$ @” jest równoważne z „$ 1” „$ 2” .... Jeśli podwójne wyrażenie występuje w jednym słowie, rozszerzenie pierwszego parametru jest łączone z początkową częścią oryginalnego słowa, a rozwinięcie ostatniego parametru jest połączone z ostatnią częścią oryginalnego słowa. Gdy nie ma parametrów pozycyjnych, „$ @” i $ @ rozwijają się do zera (tzn. Są usuwane).

Christoffer Hammarström
źródło
1

Znaczenie.

Krótko mówiąc, $@rozwija się do argumentów pozycyjnych przekazywanych przez program wywołujący do funkcji lub skryptu . Jego znaczenie zależy od kontekstu : wewnątrz funkcji rozwija się do argumentów przekazywanych do takiej funkcji. Jeśli zostanie użyty w skrypcie (nie wchodzi w zakres funkcji), rozwija się do argumentów przekazywanych do takiego skryptu.

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

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

Podział słów.

Kolejnym tematem, który ma ogromne znaczenie dla zrozumienia, jak $@zachowuje się w powłoce, jest podział słów . Powłoka dzieli tokeny na podstawie zawartości IFSzmiennej. Jego wartością domyślną jest \t\n; tj. biała spacja, tabulator i nowa linia.

Rozwijanie "$@"daje nieskazitelną kopię przekazywanych argumentów. Jednak rozszerzenie $@nie zawsze. Mówiąc dokładniej, jeśli argumenty zawierają znaki z IFS, zostaną podzielone.


Przez większość czasu, co chcesz używać to "$@"nie $@.

Luis Lavaire
źródło