Krótka odpowiedź: użyj"$@" (zwróć uwagę na podwójne cudzysłowy). Inne formy są bardzo rzadko przydatne.
"$@"jest raczej dziwną składnią. Jest on zastępowany przez wszystkie parametry pozycyjne, jako osobne pola. Jeśli nie ma parametrów pozycyjnych ( $#wynosi 0), wówczas "$@"rozwija się do zera (nie jest to pusty ciąg, ale lista z 0 elementami), jeśli istnieje jeden parametr pozycyjny, to "$@"jest równoważny "$1", jeśli są dwa parametry pozycyjne, to "$@"jest równoważny z "$1" "$2"itd.
"$@"pozwala przekazać argumenty skryptu lub funkcji do innego polecenia. Jest to bardzo przydatne w przypadku opakowań, które wykonują takie czynności, jak ustawianie zmiennych środowiskowych, przygotowywanie plików danych itp. Przed wywołaniem polecenia z tymi samymi argumentami i opcjami, które zostały wywołane przez opakowanie.
Na przykład poniższa funkcja filtruje dane wyjściowe cvs -nq update. Oprócz filtrowania danych wyjściowych i statusu zwracanego (który ma grepraczej status niż zamiast cvs), wywoływanie cvssmniektórych argumentów zachowuje się jak wywoływanie cvs -nq updatez tymi argumentami.
cvssm () { cvs -nq update "$@" | egrep -v '^[?A]'; }
"$@"rozwija się do listy parametrów pozycyjnych. W powłokach obsługujących tablice istnieje podobna składnia, aby rozwinąć listę elementów tablicy: "${array[@]}"(nawiasy klamrowe są obowiązkowe oprócz zsh). Ponownie, podwójne cudzysłowy są nieco mylące: chronią przed podziałem pola i generowaniem wzorca elementów tablicy, ale każdy element tablicy kończy się na swoim własnym polu.
Niektóre starożytne powłoki miały coś, co jest prawdopodobnie błędem: gdy nie było argumentów pozycyjnych, "$@"rozszerzono je do pojedynczego pola zawierającego pusty ciąg, zamiast do żadnego pola. Doprowadziło to do obejścia${1+"$@"} ( rozsławionego za pomocą dokumentacji Perla ). Wpływa to tylko na starsze wersje rzeczywistej powłoki Bourne'a i implementacji OSF1, a żadna z jej nowoczesnych kompatybilnych zamienników (ash, ksh, bash,…) nie jest zagrożona. /bin/shnie ma wpływu na żaden system, który został wydany w XXI wieku, o którym wiem (chyba że policzysz wersję aktualizacyjną Tru64, a nawet /usr/xpg4/bin/shjest bezpieczny, więc #!/bin/shdotyczy to tylko skryptu, a nie #!/usr/bin/env shskryptów, o ile twoja ŚCIEŻKA jest skonfigurowana pod kątem zgodności z POSIX) . Krótko mówiąc, jest to historyczna anegdota, o którą nie musisz się martwić.
"$*"zawsze rozwija się do jednego słowa. To słowo zawiera parametry pozycyjne, połączone ze spacją pomiędzy nimi. (Mówiąc bardziej ogólnie, separator jest pierwszym znakiem wartości IFSzmiennej. Jeśli wartość IFSjest pustym łańcuchem, separator jest pustym łańcuchem.) Jeśli nie ma parametrów pozycyjnych, to "$*"jest to pusty ciąg, jeśli są dwa parametry pozycyjne, a IFSich wartość domyślna "$*"jest wówczas równoważna "$1 $2"itp.
$@a $*cytaty zewnętrzne są równoważne. Rozwijają się do listy parametrów pozycyjnych, jako oddzielne pola, takie jak "$@"; ale każde wynikowe pole jest następnie dzielone na osobne pola, które są traktowane jak wzorce symboli wieloznacznych nazw plików, jak zwykle z niecytowanymi rozszerzeniami zmiennych.
Na przykład jeśli bieżący katalog zawiera trzy pliki bar, baza foonastępnie:
set -- # no positional parameters
for x in "$@"; do echo "$x"; done # prints nothing
for x in "$*"; do echo "$x"; done # prints 1 empty line
for x in $*; do echo "$x"; done # prints nothing
set -- "b* c*" "qux"
echo "$@" # prints `b* c* qux`
echo "$*" # prints `b* c* qux`
echo $* # prints `bar baz c* qux`
for x in "$@"; do echo "$x"; done # prints 2 lines: `b* c*` and `qux`
for x in "$*"; do echo "$x"; done # prints 1 lines: `b* c* qux`
for x in $*; do echo "$x"; done # prints 4 lines: `bar`, `baz`, `c*` and `qux`