Что означает знак доллара с последующим знаком at-sign ( @
) в сценарии оболочки?
Например:
umbrella_corp_options $@
Что означает знак доллара с последующим знаком at-sign ( @
) в сценарии оболочки?
Например:
umbrella_corp_options $@
Ответы:
$@
это все параметры, переданные в сценарий.
Например, если вы позвоните, ./someScript.sh foo bar
то $@
будет равно foo bar
.
Если вы делаете:
./someScript.sh foo bar
а затем внутри someScript.sh
ссылки:
umbrella_corp_options "$@"
это будет передаваться umbrella_corp_options
с каждым отдельным параметром, заключенным в двойные кавычки, что позволяет получать параметры с пробелом от вызывающей стороны и передавать их дальше.
someScript.sh foo bar "boo far"
?
$@
вовсе не обязательно исходить от параметров, получаемых в сценарий ... например, set a b "x y"; printf '(%s)' "$@"
выходы(a)(b)(x y)
$@
и$*
$@
это почти то же самое $*
, что означает «все аргументы командной строки». Они часто используются для простой передачи всех аргументов другой программе (таким образом, формируя оболочку вокруг этой другой программы).
Разница между этими двумя синтаксисами проявляется, когда у вас есть аргумент с пробелами в нем (например) и $@
в двойных кавычках:
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.
Пример: вызов
wrapper "one two three" four five "six seven"
приведет к:
"$@": 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
wrappedProgram "$*"
-> separated by single spaces.
но во втором примере они не разделены пробелами.
Это аргументы командной строки, где:
$@
= сохраняет все аргументы в списке строк
$*
= сохраняет все аргументы в виде одной строки
$#
= сохраняет количество аргументов
Использование чистых $@
средств в большинстве случаев «причиняет столько вреда программисту, сколько вы можете», потому что в большинстве случаев это приводит к проблемам с разделением слов, пробелами и другими символами в аргументах.
В (угаданном) 99% всех случаев требуется заключить его в "
: "$@"
это то, что может быть использовано для надежного перебора аргументов.
for a in "$@"; do something_with "$a"; done
for a in start_token "$@" end_token; do something_with "$a"; done
:-)
@
Расширяется до позиционных параметров, начиная с единицы. Когда раскрытие происходит в двойных кавычках, каждый параметр раскрывается в отдельное слово. То есть "$ @" эквивалентно "$ 1" "$ 2" .... Если раскрытие в двойных кавычках происходит внутри слова, расширение первого параметра объединяется с начальной частью исходного слова, и Расширение последнего параметра объединяется с последней частью исходного слова. Когда позиционные параметры отсутствуют, «$ @» и $ @ расширяются до нуля (то есть они удаляются).
Вкратце, $@
расширяется до позиционных аргументов, передаваемых от вызывающей стороны либо к функции, либо к сценарию . Его значение зависит от контекста : внутри функции оно распространяется на аргументы, передаваемые такой функции. Если он используется в скрипте (а не в области действия функции), он распространяется на аргументы, передаваемые такому скрипту.
$ cat my-sh
#! /bin/sh
echo "$@"
$ ./my-sh "Hi!"
Hi!
$ put () ( echo "$@" )
$ put "Hi!"
Hi!
Теперь еще одной темой, которая имеет первостепенное значение при понимании того, как $@
ведет себя в оболочке, является разделение слов . Оболочка разделяет токены на основе содержимого IFS
переменной. Значением по умолчанию является \t\n
; то есть, пробел, табуляция и новая строка.
Расширение "$@"
дает вам нетронутую копию переданных аргументов. Однако расширение $@
будет не всегда. Более конкретно, если аргументы содержат символы из IFS
, они будут разделены.
Большую часть времени вы хотите использовать "$@"
, а не $@
.