Расширение параметра (расширение переменной) и кавычки в кавычках
Работая в оболочке (Unix), иногда мне нужно заключать в двойные кавычки или наоборот, т.е. писать что-то вроде "foo 'bar baz' moo"
или же 'foo "bar baz" moo'
, Это может быть потому, что
- результирующая строка будет проанализирована снова (как с
eval
с ракушкойwatch
с ракушкойsshd
на некотором удаленном сервере и т. д.) и эти внутренние кавычки имеют решающее значение для различения реальных аргументов во время этого второго анализа; - или мне просто нужен исходный аргумент для включения кавычек по любой другой причине.
Некоторая двусмысленность появляется, когда вместо bar baz
У меня есть переменная, скажем $variable
, Вот что говорит POSIX:
2.2.2. Одиночные кавычки
Заключение символов в одинарные кавычки (
''
) сохраняет буквальное значение каждого символа в одинарных кавычках. Одиночная кавычка не может встречаться в одинарных кавычках.2.2.3 Двойные кавычки
Заключение символов в двойные кавычки (
""
) должен сохранять буквальное значение всех символов в двойных кавычках, за исключением символов обратной кавычки, <знак доллара>и <обратный слэш>, следующим образом:
$
Они сохранят свое особое значение, представляя расширение параметров […], форму подстановки команд […] и арифметическое расширение […].[...]
Не совсем очевидно, какое правило применяется для $variable
внутри одинарных кавычек внутри двойных кавычек (или внутри двойных кавычек внутри одинарных кавычек), поэтому я спрашиваю:
Какое правило относится к:
variable=123 echo "'$variable'"
variable=123 echo '"$variable"'
(Я знаю, что на это можно легко ответить, просто попробовав, это будет разумное исследование. Я решил поместить это усилие в ответ вики сообщества ниже).
Есть ли исключения, причуды, сюрпризы?
(Обратите внимание, что ниже приведен ответ вики-сообщества. Вместо того, чтобы добавлять отдельный ответ с другим исключением или причудой, рассмотрите возможность добавления вики-сообщества).
1 ответ
Какое правило применяется?
Просто пытаясь:
$ variable=123 $ echo "'$variable'" '123' $
$ variable=123 $ echo '"$variable"' "$variable" $
Так что внешние цитаты имеют значение. Обычные оболочки ведут себя так же: sh
, bash
, dash
, zsh
... Это из-за этого общего правила:
Если текущим символом является <обратная косая черта>, одинарная кавычка или двойная кавычка, и он не заключен в кавычки, это влияет на цитирование последующих символов до конца цитируемого текста.
Только внешние кавычки не котируются, к ним применяется правило. Внутренние кавычки заключены в кавычки, они не влияют на последующие символы.
Есть ли исключения, причуды, сюрпризы?
(Что ж, echo
может преподнести несколько сюрпризов, см. Почему printf
лучше чем echo
? Тем не менее, это отдельная проблема. Для удобства чтения ответ использует echo
с безопасным значением $variable
).
Приведенный выше код дает нам либо
'123'
или же"$variable"
, Что если нам нужно"123"
или же'$variable'
?Получить
"123"
:variable=123 echo "\"$variable\"" # ^^ ^^ escaped inner quotes
или же
variable=123 echo '"'"$variable"'"' # 1 12 23 3 outer quotes (numbered pairs) # ^ ^^^^^^^^^ ^ quoted fragments
Получить
'$variable'
:variable=123 echo "'"'$variable'"'" # 1 12 23 3 outer quotes (numbered pairs) # ^ ^^^^^^^^^ ^ quoted fragments
Вопрос отмечает, что
$
сохраняет свое особое значение в двойных кавычках. Это важно:Входные символы в строке в кавычках, которые также заключены между
$(
и соответствие)
не должны затрагиваться двойными кавычками, а скорее должны определять ту команду, чей вывод заменяет$(…)
когда слово развернуто.Это означает цитирование внутри
$(…)
следует рассматривать независимо, несмотря на внешние двойные кавычки. В самом деле:$ variable=123 $ echo "$(echo 'foo $variable')" $ # ^ ^ single-quotes matter! foo $variable $
(Заметка
echo $(stuff)
плохой код в целом; это здесь, чтобы проиллюстрировать текущую проблему).В этих двух случаях:
echo "'$variable'"
(попробовал выше)echo "$(echo 'foo $variable')"
(обсуждается здесь)
есть
$variable
внутри одинарных кавычек внутри двойных кавычек, но$(…)
сильно меняется Аналогичная ситуация сecho "`echo 'foo $variable'`"
(хотя$(…)
и галочки не совсем эквивалентны).