Я использую GNU bash
4.3.48
. Рассмотрим следующие две команды, которые отличаются только одним знаком доллара.
Команда 1:
echo "(echo " * ")"
Команда 2:
echo "$(echo " * ")"
На выходе их соответственно
(echo test.txt ppcg.sh )
и
*
Таким образом, очевидно, что в первом случае *
символ сглаживается, что означает, что первая кавычка идет со вторым, образуя пару, а третий и четвертый образуют другую пару.
Во втором случае *
это не глобус, и в выходных данных есть ровно два лишних пробела, один перед звездочкой, а второй после, что означает, что вторая кавычка идет с третьей, а первая - с четвертой.
Есть ли какие-либо другие случаи, кроме $()
конструкции, в которой кавычки не сопоставляются со следующей, а вместо этого вкладываются? Хорошо ли задокументировано это поведение, и если да, где я могу найти соответствующий документ?
Ответы:
Любые из вложенных конструкций, которые могут быть интерполированы внутри строк, могут иметь дополнительные строки внутри них: они анализируются как новый скрипт, вплоть до закрывающего маркера, и могут даже быть вложенными на нескольких уровнях глубиной. Все строки одного из них начинаются с
$
. Все они документированы в сочетании руководства Bash и спецификации языка команд оболочки POSIX.Есть несколько случаев этих конструкций:
Подстановка команды
$( ... )
, как вы нашли. POSIX определяет это поведение :Кавычки являются частью действительных сценариев оболочки, поэтому они допускаются с их обычным значением.
`
тоже.Элемент "word" в экземплярах с расширенной заменой параметров, таких как
${parameter:-word}
. Определение «слова» является :- который включает цитируемый текст и даже смешанные кавычки
a"b"c'd'e
- хотя фактическое поведение расширений немного более либерально, чем, например,${x:-hello world}
тоже работает.Арифметическое расширение с помощью
$(( ... ))
, хотя оно там в значительной степени бесполезно (но вы также можете вкладывать подстановки команд или расширения переменных, а затем использовать в них кавычки). POSIX заявляет, что :так что это поведение явно требуется. Это означает, что
echo "abc $((4 "*" 5))"
делает арифметику, а не скупость.Обратите внимание, что
$[ ... ]
арифметическое расширение старого стиля не обрабатывается одинаково: кавычки будут ошибкой, если они появятся, независимо от того, указано ли расширение в кавычках или нет. Эта форма больше не документирована и не предназначена для использования в любом случае.$"..."
, который фактически использует в"
качестве основного элемента.$"
рассматривается как единое целое.Есть еще один случай вложенности, который вы можете не ожидать, не включая кавычки, который связан с расширением скобки :
{a,b{c,d},e}
расширяется до "a bc bd e".${x:-a{b,c}d}
делает не гнездо, однако; он рассматривается как подстановка параметра, давая "a{b,c
", а затем "d}
". Это также задокументировано :Как правило, все конструкции с разделителями анализируют свои тела независимо от окружающего контекста (а исключения рассматриваются как ошибки ). В сущности, при просмотре
$(
кода подстановки команд просто просит синтаксический анализатор извлечь из тела все, что он может, как если бы это была новая программа, а затем проверяет, что ожидаемый завершающий маркер (неэкранированный)
или))
или}
) появляется после запуска подпарсера. из вещей, которые он может потреблять.Если вы думаете о функционировании синтаксического анализатора с рекурсивным спуском , это просто простая рекурсия к базовому случаю. На самом деле это проще сделать, чем другим способом, если у вас вообще есть интерполяция строк. Независимо от основной техники синтаксического анализа, оболочки, поддерживающие эти конструкции, дают одинаковый результат.
Вы можете вкладывать цитаты настолько глубоко, насколько захотите, с помощью этих конструкций, и они будут работать, как и ожидалось. Нигде не запутаться, увидев цитату в середине; вместо этого это будет началом новой строки в кавычках во внутреннем контексте.
источник
"blah/blah\n$(cat "${tmpdir}/${filename}.jpdf")"
, почему это вторая двойная кавычка не конец первой двойной кавычки (как показано подсветка синтаксиса в вашем ответе), но начало строки внутри$(...)
? Это потому, что парсер bash работает сверху вниз, а не снизу вверх?"${var-"foo"}"
(напримерecho "${-+"*"}"
, то же самое, что иecho *
в оболочке Bourne или Korn), и в следующей версии стандарта поведение будет четко определено . См. Также обсуждение на mail-archive.com/austin-group-l@opengroup.org/msg00167.htmlВозможно, рассмотрение двух примеров с
printf
(вместоecho
) поможет:Он печатает
(echo
(первое слово, включая завершающий пробел), некоторые файлы и заключительное слово)
.Скобки - это просто часть строки в кавычках
(echo
.Звездочка (теперь без кавычек, так как две двойные кавычки в паре) разворачивается как глобус в список подходящих файлов.
И затем закрывающая скобка.
Однако ваша вторая команда работает следующим образом:
$
Начинает замену команды. Это начинается свежая цитата.Звездочка
" * "
заключена в кавычки, и именно этоecho
выводит команда (здесь это команда, а не строка в кавычках) . Наконец,printf
повторно форматирует*
и печатает как< * >
.источник