Что означает $ @ в сценарии оболочки?


190

Что означает знак доллара с последующим знаком at-sign ( @) в сценарии оболочки?

Например:

umbrella_corp_options $@

4
возможный дубликат того, что $ @ ИЛИ ищет объяснение $ @ в bash
l0b0

Ответы:


243

$@это все параметры, переданные в сценарий.

Например, если вы позвоните, ./someScript.sh foo barто $@будет равно foo bar.

Если вы делаете:

./someScript.sh foo bar

а затем внутри someScript.shссылки:

umbrella_corp_options "$@"

это будет передаваться umbrella_corp_optionsс каждым отдельным параметром, заключенным в двойные кавычки, что позволяет получать параметры с пробелом от вызывающей стороны и передавать их дальше.


1
Что бы содержалось в $ @, если бы я это сделал someScript.sh foo bar "boo far"?
trusktr


7
$ @ является особенным, если написано в двойных кавычках. Тогда это приведет к списку значений в кавычках, в вашем случае, trusktr, с тремя аргументами: «foo», «bar» и «boo far».
Alfe

4
Хотя это обычно бывает, $@вовсе не обязательно исходить от параметров, получаемых в сценарий ... например, set a b "x   y"; printf '(%s)' "$@"выходы(a)(b)(x   y)
Peter.O

Мне больше нравится ответ Алфе, потому что он дает главное различие между $@и$*
donleyp

106

$@это почти то же самое $*, что означает «все аргументы командной строки». Они часто используются для простой передачи всех аргументов другой программе (таким образом, формируя оболочку вокруг этой другой программы).

Разница между этими двумя синтаксисами проявляется, когда у вас есть аргумент с пробелами в нем (например) и $@в двойных кавычках:

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

2
Они не одинаковы, и man-страница ясно о побочных эффектах $ * при использовании IFS, который не обязательно является пробелом. (Если бы они были одинаковыми, не было бы никакого смысла, кроме как совместимости, возможно, предлагать оба.)
jørgensen

6
Нет, они не. И я сказал так двумя строками ниже: «Разница между
этими

2
Alfe, добавление Кристоффером этого единственного слова «почти», чертовски изменило ситуацию, не жертвуя какой-либо краткостью или читабельностью. На самом деле я проголосовал за этот ответ (в отличие от принятого) именно из-за того тонкого акцента разницы ... - прежде чем понять, что он был почти против вашей воли! ;)
Сз.

Я думаю, что это слово имело огромное значение для людей, которые выносят вердикт сразу после прочтения первого предложения ;-), и это никогда не было против моей воли. Я действительно хотел бы написать также для этих людей.
Alfe

Очень непонятно wrappedProgram "$*"-> separated by single spaces.но во втором примере они не разделены пробелами.
Феликс Домбек

36

Это аргументы командной строки, где:

$@= сохраняет все аргументы в списке строк
$*= сохраняет все аргументы в виде одной строки
$#= сохраняет количество аргументов


(Вышеупомянутая неточность, упомянутая @iruvar, была исправлена.)
Матин Улхак

13

Использование чистых $@средств в большинстве случаев «причиняет столько вреда программисту, сколько вы можете», потому что в большинстве случаев это приводит к проблемам с разделением слов, пробелами и другими символами в аргументах.

В (угаданном) 99% всех случаев требуется заключить его в ": "$@"это то, что может быть использовано для надежного перебора аргументов.

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

4
Ваша строка может быть написана как: для; сделать что-то с "$ a"; сделано ;-)
Alfe

1
@ Я знаю, я просто забыла об этом. Думайте об этом как for a in start_token "$@" end_token; do something_with "$a"; done:-)
glglgl

9

Из руководства:

@

Расширяется до позиционных параметров, начиная с единицы. Когда раскрытие происходит в двойных кавычках, каждый параметр раскрывается в отдельное слово. То есть "$ @" эквивалентно "$ 1" "$ 2" .... Если раскрытие в двойных кавычках происходит внутри слова, расширение первого параметра объединяется с начальной частью исходного слова, и Расширение последнего параметра объединяется с последней частью исходного слова. Когда позиционные параметры отсутствуют, «$ @» и $ @ расширяются до нуля (то есть они удаляются).


1

Смысл.

Вкратце, $@расширяется до позиционных аргументов, передаваемых от вызывающей стороны либо к функции, либо к сценарию . Его значение зависит от контекста : внутри функции оно распространяется на аргументы, передаваемые такой функции. Если он используется в скрипте (а не в области действия функции), он распространяется на аргументы, передаваемые такому скрипту.

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

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

Разделение слов.

Теперь еще одной темой, которая имеет первостепенное значение при понимании того, как $@ведет себя в оболочке, является разделение слов . Оболочка разделяет токены на основе содержимого IFSпеременной. Значением по умолчанию является \t\n; то есть, пробел, табуляция и новая строка.

Расширение "$@"дает вам нетронутую копию переданных аргументов. Однако расширение $@будет не всегда. Более конкретно, если аргументы содержат символы из IFS, они будут разделены.


Большую часть времени вы хотите использовать "$@", а не $@.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.