Dostęp do args linii poleceń bash $@ vs $*

W wielu tak pytaniach i tutorialach bash widzę, że mogę uzyskać dostęp do args linii poleceń w skryptach bash na dwa sposoby:

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@

Co daje:

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2

Jaka jest różnica między $* a $@?
Kiedy należy korzystać z pierwszego i kiedy należy korzystać z drugiego?

Author: Seanny123, 2012-09-07

4 answers

Różnica pojawia się, gdy podane są parametry specjalne. Pozwól mi zilustrować różnice:

$ set -- "arg  1" "arg  2" "arg  3"

$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in "$*"; do echo "$word"; done
arg  1 arg  2 arg  3

$ for word in "$@"; do echo "$word"; done
arg  1
arg  2
arg  3

Kolejny przykład na znaczenie cytowania: zauważ, że są 2 spacje między " arg " a liczbą, ale jeśli nie zacytuję $word:

$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3

I w bash, "$@" jest "domyślną" listą do iteracji:

$ for word; do echo "$word"; done
arg  1
arg  2
arg  3
 321
Author: glenn jackman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-22 11:20:00

A nice handy overview table from the Bash Hackers Wiki :

$ * versus $@ table

Gdzie c w trzecim wierszu znajduje się pierwszy znak $IFS, wewnętrznego separatora pól; zmiennej środowiskowej.

Jeśli argumenty mają być przechowywane w zmiennej skryptowej i oczekuje się, że argumenty będą zawierać spacje, z całego serca zalecam użycie "$*" sztuczka z wewnętrznym separatorem pól $IFS ustawionym na tab .

 173
Author: Serge Stroobandt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 09:20:19

$*

Rozszerza się do parametrów pozycyjnych, zaczynając od 1. Kiedy rozszerzenie występuje w podwójnych cudzysłowach, rozszerza się do pojedynczego słowa z wartością każdego parametru oddzieloną pierwszym znakiem zmienna specjalna IFS. Oznacza to, że "$ * "jest równoważne" $1C$2C...", gdzie c jest pierwszym znakiem wartości zmiennej IFS. Jeśli IFS nie jest ustawiony, parametry są oddzielone spacjami. If IFS is null, parametry są łączone bez separatory interwencyjne.

$@

Rozszerza się do parametrów pozycyjnych, zaczynając od 1. Kiedy rozszerzenie występuje w podwójnych cudzysłowach, każdy parametr rozszerza się do osobne słowo. Oznacza to, że "$ @ " jest równoważne "$1 ""$2"... Jeśli ekspansja dwucytowa występuje w obrębie słowa, ekspansja pierwszy parametr jest połączony z początkową częścią oryginału word, a rozszerzenie ostatniego parametru jest połączone z ostatnim część oryginalne słowo. Gdy nie ma parametrów pozycyjnych, "$@"i $@ rozwijają się do zera(tzn. są usuwane).

Źródło: Bash man

 37
Author: Muffo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-07 08:36:55

$@ jest taki sam jak$*, ale każdy parametr jest cytowanym łańcuchem znaków, to znaczy parametry są przekazywane w Nienaruszonym Stanie, bez interpretacji lub rozbudowy. Oznacza to między innymi, że każdy parametr na liście argumentów jest postrzegany jako osobne słowo.

Oczywiście, "$ @ " powinno być cytowane.

Http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST

 15
Author: rkosegi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-07 08:32:33