Нужно ли заключать в кавычки подстановки команд при назначении их вывода переменной? [дубликат]

Чтобы неинтерактивное задание отвечало на SIGINT, вам необходимо создать обработчик для SIGINT:

$ ( (trap "echo Got SigInt" SIGINT; sleep 60) & ) &
[1] 13619
$ 
[1]+  Done                    ( ( trap "echo Got SigInt" SIGINT; sleep 60 ) & )
$ ps -o pid,pgid,args
  PID  PGID COMMAND
11972 11972 bash
13620 13619 bash
13621 13619 sleep 60
13622 13622 ps -o pid,pgid,args
$ kill -INT 13620
$ kill -INT 13621
$ Got SigInt

Отправка SIGINT процессу ожидания

​​Как предлагает Стефан Чазелас в комментариях, если цель состоит в том, чтобы вернуться к поведению SIGINT по умолчанию, мы можем просто использовать ловушку - SIGINT . Например:

$ ( (trap - SIGINT; sleep 60) & ) &
[1] 16690
$ ps -o pid,pgid,args
  PID  PGID COMMAND
11972 11972 bash
16691 16690 bash
16692 16690 sleep 60
16693 16693 ps -o pid,pgid,args
[1]+  Done                    ( ( trap - SIGINT; sleep 60 ) & )
$ kill -INT 16692
$ ps -o pid,pgid,args
  PID  PGID COMMAND
11972 11972 bash
16698 16698 ps -o pid,pgid,args
6
29.04.2017, 18:33
2 ответа

В качестве одной ссылки, Руководство по Bash ясно объясняет это:

Переменная может быть присвоена оператором формы

имя=[значение]

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

Без разделения на слова, без расширения имени файла, поэтому кавычки не нужны.


Что касается POSIX, раздел 2.9.1 Простые команды:

2. Слова, которые не являются переменными назначениями или перенаправлениями, должны быть расширены. Если какие-либо поля остаются после их расширения Если какие-либо поля остаются после их расширения, первое поле считается именем команды, а остальные поля являются аргументами для команды.
[...]
4.Каждое назначение переменной должно быть расширено для расширения с помощью тильды, расширения параметра, подстановки команд, арифметического расширения и удаления кавычек перед присвоением значения.

Я не уверен, что это должно интерпретироваться как означающее, что разделение поля происходит только для расширений, сделанных на шаге 2? В шаге 4 не упоминается разделение полей, хотя в разделе Разделение полей также не упоминаются назначения переменных как исключение для создания нескольких полей.

3
27.01.2020, 20:27

Вам не нужно заключать в кавычки выражение в правой части присваивания.

Что вас раздражает, так это то, что другой ответ рекомендует цитировать тем не менее. Но это касается только обслуживания кода.

Рассмотрим следующий правильный пример:

DIRNAME=$(dirname "$FILE")
echo "debug: dirname is $DIRNAME"
ls "$DIRNAME"

Теперь, поработав с этим скриптом некоторое время, вы можете подумать, что отладочное сообщение может быть удалено. Таким образом, с помощью редактора вы удалите эхо-строку. Затем вы заметите, что вам больше не нужна переменная DIRNAME, и вы просто перемещаете команду ls, чтобы заменить левый сайт назначения. Теперь вы можете забыть добавить нужные кавычки и в итоге получите вот такой неработающий скрипт:

ls $(dirname "$FILE")

Вероятность такой ошибки еще выше, если первый автор знаток оболочки, но второй редактор новичок.

Конечно, можно спорить о том, действительно ли эта рекомендация избегать возможности переносимой оболочки полезна. Лично я делаю это в основном так, как он рекомендует. Я также делаю это для более «простых» назначений, таких как: var="${foo}" (включая лишние фигурные скобки).

4
27.01.2020, 20:27

Теги

Похожие вопросы