В чем разница между кавычками «…», «…», $ «…» и $ «…»?


49

Иногда я вижу сценарии использовать все эти различные способы процитировать текст: "...", '...', $'...', и $"...". Почему используется так много разных цитат?

Они ведут себя по-разному или влияют на то, что я могу сделать внутри них?


1
Возможен межсайтовый дубликат. Этот ответ содержит краткое изложение (или ссылки на) семантики всех различных типов цитат.
Чепнер

Ответы:


66

Все это означает что-то другое, и вы можете писать разные вещи внутри них (или одни и те же вещи, имеющие разное значение). Различные типы кавычек интерпретируют различные escape-последовательности внутри них ( \something), или разрешают или не допускают интерполяции переменных ( $something) и другие виды расширения внутри них.

Короче говоря:

  • '...' полностью буквально.
  • "..." позволяет как переменные, так и встроенные символы кавычек.
  • $'...'выполняет экранирование символов \n, но не расширяет переменные.
  • $"..." для перевода на человеческий язык в Bash и ksh.

«Одиночные кавычки»

Все, что вы пишете между одинарными кавычками, трактуется буквально, а не обрабатывается вообще. Обратная косая черта и знаки доллара там не имеют особого значения. Это означает, что вы не можете использовать обратную косую черту символа (включая другие одинарные кавычки!), Интерполировать переменную или использовать любую другую функцию оболочки.

Все эти примеры приводят буквально к тому, что написано между кавычками:

'hello world'                     => hello world
'/pkg/bin:$PATH'                  => /pkg/bin:$PATH
'hello\nworld'                    => hello\nworld
'`echo abc`'                      => `echo abc`
'I\'dn\'t've'                     => I\dn'tve

Последняя сложна - есть две строки в одинарных кавычках, которые запускаются вместе с текстом без кавычек. Первый содержит I\. Текст dn\'tбез кавычек содержит одну кавычку, которая экранируется на уровне оболочки , поэтому он не запускает строку в кавычках и включается в виде буквенного символа (так, dn't). Последняя строка в кавычках просто ve. Все они соединяются в одно слово обычным образом, как работает оболочка.

Несколько распространенная идиома для объединения буквального текста и переменных - это запускать их вместе так:

'let x="'$PATH\"

приведет к

let x="/usr/bin:/bin"

как одно слово (лучше на $PATHвсякий случай также заключить в двойные кавычки - пробелы или символы-заглушки в значении переменной могут быть обработаны иначе - но ради читабельного бегущего примера у меня нет).


"Двойные кавычки"

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

Есть две категории раскрытия, которые происходят внутри двойных кавычек:

Внутри кавычек обратная косая черта может блокировать эти расширения, помещая их перед $или `. Он также может экранировать закрывающую двойную кавычку, поэтому \"включается только "в вашу строку или другую обратную косую черту. Любая другая обратная косая черта в буквальном смысле сохраняется - здесь нет выходов для создания других персонажей, и она не удаляется.

Некоторые из этих примеров действуют иначе, чем раньше, а некоторые нет:

"hello world"                     => hello world
"/pkg/bin:$PATH"                  => /pkg/bin:/bin:/usr/bin
"hello\nworld"                    => hello\nworld
"hello\\nworld"                   => hello\nworld
"`echo abc`"                      => abc
"I\'dn\'t've"                     => I\'dn\'t've
"I'dn't've"                       => I'dn't've
"I\"dn\"t've"                     => I"dn"t've

$ 'ANSI-C цитирование'

Этот тип цитирования позволяет обрабатывать обратные слэши в стиле C, но не встроенные переменные или подстановки. Это единственный вид цитирования, который поддерживает экранирование символов .

Это расширение от ksh, которое теперь поддерживается в Bash, zsh и некоторых других оболочках. Он еще не является частью стандарта POSIX, поэтому максимально переносимые сценарии не могут его использовать, но сценарии Bash или ksh бесплатны.

Все эти побеги могут быть использованы с их значениями C: \a, \b, \f, \n, \r, \t, \v, и буквальные ускользает \\, \', \", и \?. Они также поддерживают расширения \e(escape-символ) и в Bash и ksh \cx(что будет введено Ctrl-x , например, \cMвозврат каретки). Снаряды имеют ряд собственных расширений.

Это также позволяет использовать четыре вида экранированных символов:

  • \nnn, один байт с восьмеричным значением nnn
  • \xHH, один байт с шестнадцатеричным значением HH
  • \uHHHHкод Unicode с шестнадцатеричным индексом HHHH
  • \UHHHHHHHHкод Unicode с шестнадцатеричным индексом HHHHHHHH

Все эти цифры являются необязательными после первого.

$и не `имеют значения и сохраняются буквально, поэтому вы не можете включить туда переменную.

$'hello world'                    => hello world
$'/pkg/bin:$PATH'                 => /pkg/bin:$PATH
$'hello\nworld'                   => hello
                                     world
$'`echo abc`'                     => `echo abc`
$'I\'dn\'t\'ve'                   => I'dn't've
$'\U1f574\u263A'                  => 🕴☺

Большинство из этих побегов можно имитировать с помощью в printfкоманду , хотя POSIX требует только \\, \a, \b, \f, \n, \r, \t, \v, и \nnnработать там. Вы можете использовать подстановки команд , чтобы вставлять printfв двойные кавычки , если это необходимо: "Path:$(printf '\t')$PATH".


$ "Перевод локали"

Это специфичное для ksh и Bash расширение для локализации текстовых строк на естественном языке, которое ищет часть внутри кавычек в каталоге сообщений. Сначала он выполняет все расширения двойных кавычек. Если строка не найдена в базе данных переводов, она используется как собственный перевод. Встроенное предположение состоит в том, что строки на английском языке.

Вы, вероятно, не хотите использовать этот, но если вы видите его, вы можете рассматривать его как обычные двойные кавычки.


Следует отметить, что не существует вида цитирования, который бы позволял расширять как встроенные параметры, так и экранированные символы. В большинстве случаев, когда вы этого хотите, вам лучше (безопаснее) использовать printf:

printf 'New path: \e[1m%s\e[0m' "/pkg/bin:$PATH:"

Это четко разделяет, какие части подлежат экранированию символов, а какие являются значениями данных.

Другой заключается в том, что все эти стили цитирования создают одно «слово» в оболочке, если только $@ расширение ${x[@]}двойного массива не используется внутри двойных кавычек. Обе формы в одинарных кавычках - это всегда одно слово и никогда не расширяются.


$"..."также из ksh93, добавлен в bash в 2.0.
Стефан Шазелас

Там нет \cXв zsh. Это \CXили \C-Xтам ( \cуже имеет особое значение echo)
Стефан Шазелас

'let x="'$PATH\"неверно в контекстах списков в оболочках, отличных от того, zshчто $PATHне заключено в кавычки (поэтому будет подвержено split + glob, что вам здесь не нужно).
Стефан Шазелас

Возможно, вы захотите уточнить, что вы говорите о оболочках, похожих на корн, обработка цитат отличается в csh, rc, fish ...
Стефан Шазелас

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.