Почему --text = «$ @» пропускает только первое слово?

9

Когда я запускаю следующий скрипт с такими аргументами, как arg1 arg2 arg3:

#!/bin/bash
zenity --entry --text="$@"

zenity создает диалог ввода с таким текстом: «arg1», тогда как я ожидаю «arg1 arg2 arg3»

Если я использую переменную, подобную следующему сценарию, она показывает все аргументы для текста ввода.

#!/bin/bash
text="$@"
zenity --entry --text="$text"

В чем разница между этими скриптами? Почему первый заменяется $@только первым аргументом?

Омид
источник

Ответы:

16

$@расширяется до отдельных слов (тогда как $*расширяется до одного слова), как описано в bashруководстве . Таким образом, когда вы пишете

zenity --text="$@"

расширяется до

zenity --text="$1" "$2" "$3"

Однако присваивание переменных оболочки не разделяется на слова. Обратите внимание, что разделение полей / слов в списке расширений для присвоений переменных в bashруководстве отсутствует . Такое поведение согласуется со спецификацией POSIX . Итак, когда вы пишете

text="$@"

переменная textполучает все позиционные параметры как одно слово, эквивалентное тому, что вы написали text="$*". Действительно, именно по этой причине двойные кавычки часто не нужны при назначении переменных. Обе

text=$@

а также

text=$*

совершенно безопасны.

Так,

text=$@
zenity --option="$text"

расширяется "$text"до одного слова, поэтому это работает. Обратите внимание, --option="$@"что это обычный аргумент команды zenity, а не присвоение переменной оболочки, поэтому разделение слов происходит здесь, а не в text=$@.

jw013
источник
1
+1. Это также будет работать: zenity --text="$*"- "$*"расширяется до одного слова.
Гленн Джекман
+1 за то, что научил меня одной вещи: человек! = Документация. Я должен был искать информацию Bash, она также содержит раздел руководства, на который вы ссылались.
manatwork
7

$@ расширяем каждый параметр в отдельном слове, становясь

zenity --entry --text="arg1" "arg2" "arg3" # syntactically wrong for zenity

Используйте $*вместо этого, чтобы развернуть его одним словом

zenity --entry --text="$*"

который станет

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
manatwork
источник
Просьба пролить свет на то, почему вариант $ text из вопроса ОП работает, как и ожидалось
iruvar
@ChandraRavoori, ты поймал меня с этим. Согласно руководству «Разделение слов не выполняется, за исключением« $ @ »» и «Если в слове происходит раскрытие в двойных кавычках, расширение первого параметра объединяется с начальной частью исходного слова, и расширение последнего параметра соединяется с последней частью исходного слова », так что я ожидаю, text="$@"что будет расширен до того text="arg1" "arg2" "arg3", что не получится . Но, конечно, это не так.
manatwork
@ChandraRavoori Причина в том, что при назначении переменных не происходит разделения полей. Я объясню более подробно в моем ответе .
jw013
@ jw013: Но в соответствии с Bash Reference Manual , "$@" делает претерпевают слово расщепления, даже в назначении переменного.
Руах
@ruakh Руководство по bash не говорит этого, насколько я знаю. У вас есть цитата?
jw013