Как использовать специальный символ как нормальный?


13

Многие вопросы, например, «Как ввести символ двойной кавычки (»)? нас спрашивают, и мы не хотим загромождать наше сообщество одним и тем же ответом (введите его, как \"будто он не заключен в 's, "если заключен в 's.) Итак, вопрос здесь.

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

echo Updates (11)

Итак, как ввести эти символы в терминале, как если бы они были нормальными?

!#$^&*?[](){}<>~;'"\|<space><tab><newline>

Я не знаю оболочки Unix, где возврат каретки особенный. =, @И %специальные в некоторых оболочках в некоторых контекстах.
Стефан Шазелас

@ StéphaneChazelas Umm ... возврат каретки ^M( ^J) для меня действует как перевод строки ( ) (Ubuntu 14.04, sh).
EKons

Нет, ваш драйвер терминала преобразуется ^Mво ^Jвходной, но ^Mне является специальным для оболочки и не нуждается в кавычках. Напечатайте, echo ^V^M | hdи вы увидите символ 0d (и 0a, добавленный echo).
Стефан Шазелас

@ StéphaneChazelas Умм ... Я не знаю, что hd, может быть xxd, лучше, как шестнадцатеричный зритель.
EKons

Какой бы ни. Используйте POSIX od -tx1или sed -n lvx's xxd, если у вас его нет hd. Некоторые системы также имеют cat -vteилиcat -A
Стефан Chazelas

Ответы:


26

Это очень зависит от оболочки. Проверьте руководство вашей оболочки для деталей.

Также обратите внимание, что некоторые символы являются особенными только в некоторых контекстах. Например, в большинстве оболочек, *и ?специальные только в списке контекстов, в POSIX или CSH-подобных оболочек, ~является особенным только в начале слова или после некоторых символов , как :. То же самое для =в zsh. В некоторых оболочках [это особенное значение только при условии соответствия (с некоторыми ограничениями) a ].

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

Операторы цитирования (для удаления особого значения этих символов) также сильно различаются между оболочками.

Борновоподобные раковины

Сводка по Bourne-подобным оболочкам (это оболочки, которые, как известно, вызывались shв той или иной системе с 80-х годов):

Оболочка Борна

Специальные символы:

  • "\'&|;()^`<>$, пробел, перевод строки и табуляция являются специальными в простых командных строках, когда они не заключены в кавычки.
  • #(кроме ранней версии) является специальным в начале строки или после пробела без кавычек, табуляции или &|()^<>;`.
  • {и }отличаются только тем, что они являются ключевыми словами оболочки (так что только слова в командной позиции).
  • *?[являются особыми в качестве операторов глобирования, поэтому только в контексте списка. В случае [, это то, [...]что является оператором смещения, [или ]нужно или только нужно заключить в кавычки, чтобы удалить специальное значение.
  • =особенный, когда он используется как оператор присваивания. То есть в простой команде для всех слов, которые не следуют за аргументом (кроме как после set -k).

Цитирование операторов

  • \\<newline>заключает в кавычки все специальные символы, кроме новой строки ( это способ продолжить длинную логическую строку на следующей физической строке, чтобы удалить последовательность). Обратите внимание, что обратные пометки добавляют дополнительную сложность, поскольку внутри них \используются в первую очередь, чтобы избежать закрывающего обратного удара и помочь парсеру. Внутри двойных кавычек \может использоваться только для экранирования ", $и `( \<newline>все еще является продолжением строки). Внутри документа здесь то же самое, за исключением ". \это единственный способ избежать символов внутри здесь документов.
  • "..."двойные кавычки экранируют все символы, кроме себя \, $и `.
  • '...' одинарные кавычки экранируют все символы, кроме себя.

POSIX снаряды

Оболочки POSIX ведут себя в основном как оболочка Борна, за исключением того, что:

ksh

как POSIX за исключением того, что:

  • {string}является особенным, если строка содержит кавычки ,(или ..в некоторых случаях и с некоторыми версиями).
  • В ksh93 есть дополнительный специальный оператор цитирования: $'...'со сложными правилами. Этот оператор также найден (с некоторыми вариациями) в bash, zsh, mkshи FreeBSD и BusyBox sh.
  • ksh93также есть $"..."оператор цитирования, который работает аналогично, "..."за исключением того, что строка подлежит локализации (может быть настроена так, что она переводит на язык пользователя). mkshигнорирует $в $"...".

bash

нравится, ksh93но:

  • в однобайтовых локалях символов все пустые (в соответствии с локалью) символы рассматриваются как разделители (например, пробел или табуляция). По сути, это означает, что вы должны заключать в кавычки все байты с 8-м битом, установленным на случай, если они могут быть пустым символом в некоторой локали.
  • Когда расширение истории csh включено, как в интерактивных экземплярах, оно !является особенным в некоторых контекстах, и двойные кавычки не всегда избегают его. И ^особенно в начале команды.

zsh

нравится, ksh93но:

  • то же самое, что и bashдля расширения истории csh
  • =является особенным в качестве первого символа слова ( =lsрасширяется до /bin/ls).
  • {а }также может открывать и закрывать группы команд, когда они не разделены (как в {echo text}работах, подобных тем, что у Борна { echo text;}).
  • за исключением [одного, [потребности цитируются, даже если они не закрыты ].
  • С extendedglobвключенной опцией #, ^и ~операторы globbing.
  • С bracecclопцией, {non-empty-string}это особенное.
  • $"..." не поддерживается.
  • как особая причуда, ?не является особой, когда следует за %(даже в кавычках или расширенной) в начале слова (чтобы позволить %?nameзадание)
  • rcquotesвариант (не включена по умолчанию) позволяет ввести одиночные кавычки как ''внутри одиночных кавычек а ля rc(см . ниже)

yash

как POSIXкроме этого.

  • все пустые символы считаются разделителями.
  • С помощью brace-expandопции реализует расширение скобки в стиле zsh.

Для всех оболочек существуют особые контексты, в которых цитирование работает по-разному. Мы уже упоминали здесь документы и обратные ссылки, но есть также [[...]]в ksh и нескольких других оболочках, POSIX $((...)), caseконструкциях ...

Также обратите внимание, что цитирование может иметь другие побочные эффекты, когда речь идет о расширениях (с двойными кавычками) или при применении к разделителям документов. Это также отключает зарезервированные слова и влияет на расширение псевдонима.

Резюме

В Bourne-подобных оболочках !#$^&*?[(){}<>~;'"`\|=SPC, TAB, NEWLINE и некоторые байты с установленным 8-м битом являются или могут быть специальными (по крайней мере, в некоторых контекстах).

Чтобы убрать особое значение, чтобы к ним относились буквально, используйте цитаты.

Использование:

  • '...' удалить особое значение каждого символа:

    printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
    single arguments (without the enclosing quotes) to `printf`'
  • \ удалить специальное значение только одного символа:

    printf '<%s>\n' foo bar\ baz #comment

    Выше только символ пробела, которому предшествует a \, передается буквально printf. Другие обрабатываются оболочкой как разделители токенов.

  • использовать "..."процитировать символы в то же время позволяя расширение параметров ( $var, $#, ${foo#bar}...), арифметическая разложение ( $((1+1))также $[1+1]в некоторых оболочках) и подстановки команд ( $(...)или старой форме `...`. На самом деле, большую часть времени, вы хотите поместить эти расширения внутри двойные кавычки в любом случае . Вы можете использовать \внутри, "..."чтобы удалить специальное значение символов, которые все еще особенные (но только их).
  • если строка содержит 'символ, вы все равно можете использовать '...'для остальных и использовать другие механизмы цитирования, которые могут заключать в кавычки 'как "'"или \'или (где доступно) $'\'':

    echo 'This is "tricky", isn'\''t it?'
  • Используйте современную $(...)форму подстановки команд. Используйте старый только `...`для совместимости с оболочкой Bourne, то есть для очень старой системы, и только в назначениях переменных, как в not use:

    echo "`echo "foo bar"`"

    Что не будет работать с оболочкой Bourne или AT & T версиями ksh. Или:

    echo "`echo \"foo bar\"`"

    Который будет работать с Bourne и AT & T ksh, но не с yash, а использовать:

    var=`echo "foo bar"`; echo "$var"

    который будет работать со всеми.

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

    var=`printf '%s\n' '\\'`

    Будет хранить только одну обратную косую черту внутри $var, потому что есть дополнительный уровень обработки обратной косой черты (для \, `и $(а также "когда они заключены в кавычки, кроме как в yash)) внутри обратных кавычек, поэтому вам нужно либо

    var=`printf '%s\n' '\\\\'`

    или

    var=`printf '%s\n' '\\\'

    вместо.

Csh семья

csh и tcsh имеют существенно различный синтаксис, хотя с оболочкой Bourne все еще много общего, поскольку они имеют общее наследие.

Специальные символы:

  • "\'&|;()^`<>$, пробел, перевод строки и табуляция являются специальными везде, когда они не указаны.
  • #(csh - это оболочка, представленная #в качестве лидера комментария), особенная в начале скрипта или после пробела без кавычек, табуляции или новой строки.
  • *?[ являются особенными, как операторы globbing, так и в контексте списка
  • {non-empty-string} является особенным (csh - оболочка, которая ввела расширение скобки).
  • !и ^являются особенными как часть расширения истории (опять же, изобретение csh), а правила цитирования особенные.
  • ~ (расширение тильды также изобретение csh) особенное в некоторых контекстах.

Цитирование операторов

Они такие же, как для оболочки Bourne, но поведение отличается. tcsh ведет себя как csh с точки зрения синтаксиса, вы обнаружите, что многие версии csh имеют неприятные ошибки. Получите последнюю версию tcsh, чтобы получить примерно рабочую версию csh.

  • \экранирует один символ, кроме новой строки (так же, как и для оболочки Bourne). Это единственный оператор цитирования, который может сбежать !. \<newline>не избегает этого, но преобразует его из разделителя команд в разделитель токенов (например, пробел)
  • "..."ускользает все символы , кроме самого, $, `, новой строки и !. В отличие от оболочки Bourne, вы не можете использовать \для побега $и `изнутри "...", но вы можете использовать \для выхода !или перехода на новую строку (но не на себя, кроме как перед !символом a или переводом строки). Литерал !есть, "\!"а литерал \!есть "\\!".
  • '...' экранирует все символы кроме себя !и перевода строки. Как для двойных кавычек, так !и перевод строки может быть экранирован обратной косой чертой.
  • Подстановка команд производится только через `...`синтаксис и вряд ли может использоваться надежно.
  • Подстановка переменных также довольно плохо спроектирована и подвержена ошибкам. $var:qОператор помогает писать более надежные коду с участием переменных.

Резюме

Держитесь подальше от csh, если можете. Если вы не можете использовать:

  • одинарные кавычки, чтобы процитировать большинство символов. !а новая строка еще нужна \.
  • \ может избежать большинства персонажей
  • "..."Можно разрешить некоторые расширения внутри него, но это довольно глючно, если они включают символы новой строки и / или обратной косой черты, лучше всего использовать только одинарные кавычки и $var:qдля расширения переменных. Вам нужно будет использовать циклы, если вы хотите надежно объединить элементы массива.

rc семья

rcэто plan9оболочка , и как его потомки esи akangaбыла перенесена на Unix и Unix-подобные. Это оболочка с намного более чистым и лучшим синтаксисом, которую каждый использовал бы, если бы мы не были привязаны к оболочкам типа Борна для обратной совместимости.

rc/akanga

Специальные символы

  • #;&|^$=`'{}()<>, SPC, TAB и NEWLINE всегда особенные, если они не указаны.
  • *?[ работают операторы.

Оператор цитирования

'...'является единственным оператором цитирования. Буква 'написана ''в одинарных кавычках, как в:

 echo 'it''s so simple isn''t it?'

es

esможно рассматривать как экспериментальную оболочку на основе rc.

Хотя есть несколько отличий. Интересным для этого Q / A является то, что \он также является оператором кавычек ( который заключает в кавычки все специальные символы, кроме новой строки) и может также использоваться для введения escape-последовательностей, таких как \nдля новой строки, \bдля обратной косой черты ...

рыбы

Рыба является относительным новичком (около 2005 г.), в первую очередь предназначена для интерактивного использования, а также имеет существенно отличающийся синтаксис от других оболочек.

специальные символы

  • "'\()$%{}^<>;&|всегда особенный, если не указан (обратите внимание на %(для расширения pid), как на значительное отличие от других оболочек, и `не является особенным)
  • # (комментарий) особенный при переходе без кавычек, табуляции, новой строки или ;&|^<>
  • *?(но не [...]) операторы

Цитирование операторов

  • \заключает в кавычки один специальный символ, кроме новой строки, но имейте в виду, что он также используется как вводная последовательность C ( \n, \b...). Я \nне цитируемый, nа перевод строки.
  • "..."цитирует все, кроме себя, $и обратный слеш и обратный слеш могут быть использованы, чтобы избежать их. \<newline>продолжение строки (удалено) внутри "...".
  • '...'цитирует все, кроме себя и \, и вы можете использовать обратную косую черту, чтобы избежать тех.

Я включил только специальный, во всех контекстах (так , что cдействует так же , как \c, cне выхода c: command not foundна STDERR и т.д.) И я говорю о shздесь. Кроме того, помните, что это вопрос «зачистки», т. Е. Он предназначен для того, чтобы охватить всех таких персонажей, поэтому не нужно задавать 19+ вопросов. Вопрос был опубликован благодаря инциденту, когда разные персонажи задавали разные вопросы, и мы, конечно же, хотим привести его в порядок!
EKons

Ну, ?[это операторы-сабли, но они не особенные во всех контекстах, но, *похоже , таковы , потому что echo *плохо echoотражают содержимое текущего каталога (ничего не избегая). echo ?повторяет буквальное ?и echo [повторяет буквальное [. Кроме того, также ]является глобатором.
EKons

1
@ ΈρικΚωνσταντόπουλος, *поскольку глобус распространяется на все не скрытые файлы, ?на не скрытые односимвольные файлы, [a-z]на файлы, имя которых состоит из одного символа между a и z и так далее. Когда они не совпадают ни с одним файлом (как в вашем случае для ?), в зависимости от оболочки вы получаете ошибку несоответствия или шаблон расширяется до самого себя. В любом случае, даже в оболочке, где они расширяются, они должны заключаться в кавычки в случае, если они могут соответствовать файлу.
Стефан Шазелас

Но, не как шар, *все еще расширяется к чему-то.
EKons

@ ΈρικΚωνσταντόπουλος, *похоже ?, если он не совпадает (для случая *одного, то есть, когда в текущем каталоге есть только скрытые файлы, потому a*что там, где нет файла, имя которого начинается с a...), он либо расширяется до сама по себе ( в большинстве Bourne-подобных оболочек), или выдает ошибку нет матчей ( csh, tcsh, fish(предупреждение), zsh, bash -O failglob, ранние Unix оболочки), (или ничего не содержит, с возможностью nullglob некоторых оболочек или , если есть еще один шаблон , который расширяется в что-то в csh, tcsh, zsh -o cshnullglob, ранние оболочки unix).
Стефан Шазелас

4

1. Побег

Удалите все эти символы с помощью символа \, как это (не работает с символами перевода строки / возврата каретки):

$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.

2. Двойная кавычка

Заключите весь текст в "s, вот так:

$ var=variables;echo "Enclose text in \"s. You can also use $var in them. `echo Surprise!!!`"
Enclose text in "s. You can also use variables in them. Surprise!!!

3. Одиночная кавычка

То же, что двойная кавычка, но специального токена нет.

$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof

1
Вы описываете поведение fishоболочки, а не оболочек типа Борна, где одинарные кавычки указывают каждый символ (обратный слеш не является особенным внутри '...'). Обратите внимание, что в fish, %также является специальным символом.
Стефан Шазелас

@ StéphaneChazelas Я не знаю, как fishработает, но мой опыт показывает , что sh, echo '\\'эхо \ и echo '\''отголоски '.
EKons

1
echo '\\'выводит \, потому что вы echoрасширяете escape-последовательности ANSI C ( для этого echoнужны некоторые реализации echo -e '\\'). printf '%s\n' '\\'выходы \\.
Стефан Шазелас

Обратите внимание, что shне идентифицирует конкретную оболочку, существует и было много разных и часто несовместимых оболочек, называемых sh.
Стефан Шазелас

@ StéphaneChazelas О, ладно, я сейчас поменяю. Кстати, \'это специальный токен внутри символьной последовательности в одинарных кавычках?
EKons
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.