Що означає $ @ у сценарії оболонки?


189

Що означає знак долара, який супроводжується знаком at-sign ( @) у сценарії оболонки?

Наприклад:

umbrella_corp_options $@

4
можливий дублікат того, що $ @ АБО шукає пояснення $ @ in bash
l0b0,

Відповіді:


242

$@- це всі параметри, передані сценарію.

Наприклад, якщо ви зателефонували, ./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".
Альфе

4
Хоча це взагалі так, $@це не обов'язково походить від параметрів, переданих до сценарію ... наприклад; set a b "x   y"; printf '(%s)' "$@"виходи(a)(b)(x   y)
Пітер.О

Мені подобається відповідь $@$*
Алфе,

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
Вони не однакові, і розміщення сторінки зрозуміло щодо побічних ефектів $ * за допомогою IFS - що не обов'язково є простором. (Якби вони були однакові, не було б жодного сенсу, окрім сумісності, можливо, у тому, щоб пропонувати і те й інше.)
jørgensen

6
Ні, вони не. І я сказав так два рядки нижче: "Різниця між двома ..." Для отримання коротких пропозицій та підвищення читабельності читачеві доводиться прочитати більше одного речення, перш ніж виносити вердикт: - /
Alfe

2
Альфе, введення Крістоффера цього одного слова "ледь не" призвело до певної різниці, не приносячи шкоди ніякій чіткості чи читанні. Насправді я підтримав цю відповідь (на відміну від прийнятої) саме через той тонкий акцент різниці ... - перш ніж усвідомити, що це майже проти вашої волі! ;)
Sz.

Я думаю, що це слово мало певне значення для людей, які виносили вердикт відразу після прочитання першого речення ;-), і це ніколи не було проти моєї волі. Мені б дуже хотілося писати і для цих людей.
Альфе

Дуже незрозуміло. wrappedProgram "$*"-> separated by single spaces.але у вашому 2-му прикладі вони не розділені між собою проміжками.
Фелікс Домбек

36

Це аргументи командного рядка, де:

$@= зберігає всі аргументи у списку string
$*= зберігає всі аргументи у вигляді однієї строки
$#= зберігає кількість аргументів


(Виправлена ​​вищенаведена неточність, яку згадував @iruvar.)
Матін Ульхак,

13

Використання чистого $@засобу в більшості випадків "завдає шкоди програмісту настільки сильно, як ви можете", оскільки в більшості випадків це призводить до проблем з розділенням слова, з пробілами та іншими символами в аргументах.

У (здогадався) 99% всіх випадків, потрібно вкласти це ": "$@"чи можна використати для надійної ітерації аргументів.

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

4
Ваш рядок може бути записаний так: для a; робити щось_з "$ a"; зроблено ;-)
Альфе

1
@Alfe Я знаю, я просто забув це. Подумайте про це як 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.