Расширение параметра (расширение переменной) и кавычки в кавычках
Работая в оболочке (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'`"(хотя$(…)и галочки не совсем эквивалентны).