Есть ли исчерпывающий список символов, которые нужно экранировать в Bash? Это можно проверить только с sed
?
В частности, я проверял, %
нужно ли бежать или нет. Я попытался
echo "h%h" | sed 's/%/i/g'
и работал нормально, без побега %
. Значит ли это, что %
не нужно бежать? Был ли это хороший способ проверить необходимость?
И более общий: они одни и те же символы , чтобы бежать в shell
и bash
?
Ответы:
Есть два простых и безопасных правила, которые работают не только в,
sh
но и вbash
.1. Поместите всю строку в одинарные кавычки
Это работает для всех символов, кроме одной кавычки. Чтобы избежать одиночной кавычки, закройте перед ней кавычку, вставьте одинарную кавычку и снова откройте кавычку.
команда sed:
sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2. Избегайте каждого символа с обратной косой чертой
Это работает для всех персонажей, кроме новой строки. Для символов новой строки используйте одинарные или двойные кавычки. Пустые строки все еще должны быть обработаны - заменить на
""
СЕПГ команда:
sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.2b. Более читаемая версия 2
Есть простой безопасный набор символов, например
[a-zA-Z0-9,._+:@%/-]
, который можно оставить без экранирования, чтобы сделать его более читабельнымСЕПГ команда:
LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.Обратите внимание, что в программе sed невозможно узнать, заканчивается ли последняя строка ввода байтом новой строки (кроме случаев, когда он пуст). Вот почему обе приведенные выше команды sed предполагают, что это не так. Вы можете добавить цитируемую новую строку вручную.
Обратите внимание, что переменные оболочки определены только для текста в смысле POSIX. Обработка двоичных данных не определена. Для реализаций, которые имеют значение, двоичный код работает за исключением байтов NUL (поскольку переменные реализованы с помощью строк C и предназначены для использования в качестве строк C, а именно аргументов программы), но вам следует переключиться на «двоичный» языковой стандарт, такой как latin1 ,
(Вы можете легко проверить правила, прочитав спецификацию POSIX для
sh
. Для bash обратитесь к справочному руководству, связанному с @AustinPhillips)источник
sed
, но требуетbash
.формат, который можно использовать в качестве ввода оболочки
Для такого запроса существует специальная
printf
директива формата (%q
):Некоторые образцы:
Это можно использовать и через переменные:
Быстрая проверка со всеми (128) байтами ascii:
Обратите внимание, что все байты от 128 до 255 должны быть экранированы.
Это должно сделать что-то вроде:
Где первое поле является шестнадцатеричным значением байта, второе содержит,
E
если символ должен быть экранирован, а третье поле показывает экранированное представление символа.Почему
,
?Вы могли видеть некоторые символы, которые не всегда нужно экранировать, например
,
,}
и{
.Так что не всегда , но когда - то :
или
но все равно
источник
subprocess.Popen(['bash', '-c', 'printf "%q\0" "$@"', '_', arbitrary_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
предоставит вам правильную версию в кавычкахarbitrary_string
.%q
был сломан в течение долгого времени - если мой разум хорошо мне служит, ошибка была исправлена (но, возможно, все еще не исправлена) в 2013 году после того, как была сломана в течение ~ 10 лет. Так что не надейся на это.shlex.quote()
(> = 3.3,pipes.quote()
- недокументированный - для более старых версий) также выполнит работу и создаст более читаемую версию (добавляя кавычки и экранируя, если необходимо) большинства строк, без необходимости порождать раковину.,
. Я был удивлен, узнав, что встроенный Bashprintf -- %q ','
дает\,
, но/usr/bin/printf -- %q ','
дает,
(не экранированный). То же самое для других символов:{
,|
,}
,~
.Чтобы избавить кого-то от необходимости использовать RTFM ... в bash :
... так что если вы избежите этого (и сама цитата, конечно), вы, вероятно, в порядке.
Если вы придерживаетесь более консервативного подхода «когда сомневаетесь, избегайте его», следует избегать использования вместо них символов со специальным значением, не избегая идентифицирующих символов (т. Е. Букв ASCII, цифр или «_»). Очень маловероятно, что они когда-либо (т.е. в какой-то странной оболочке POSIX-ish) будут иметь особое значение и, следовательно, должны быть экранированы.
источник
Используя эту
print '%q'
технику , мы можем запустить цикл, чтобы узнать, какие символы особенные:Это дает такой вывод:
Некоторые результаты
,
выглядят немного подозрительно. Было бы интересно получить отзывы @ CharlesDuffy по этому вопросу.источник
,
выглядеть немного подозрительно в последнем абзаце моего ответа%q
он не знает, где внутри оболочки вы планируете использовать символ, поэтому он будет экранировать все символы, которые могут иметь особое значение в любом возможном контексте оболочки.,
само по себе не имеет особого значения для оболочки, но, как указал @FHauri в своем ответе, оно имеет особое значение в{...}
расширении фигурных скобок: gnu.org/savannah-checkouts/gnu/bash/manual/… Это как! который также требует расширения только в определенных ситуациях, а не в целом:echo Hello World!
работает просто отлично, но неecho test!test
получится.Символы, которые нужно экранировать, отличаются в Bourne или POSIX от Bash. Обычно (очень) Bash является надмножеством этих оболочек, поэтому все, что вы сбежали,
shell
должно быть сброшено в Bash.Хорошим общим правилом было бы «если сомневаешься, избегай его». Но экранирование некоторых символов придает им особое значение, например
\n
. Они перечислены наman bash
страницах подQuoting
иecho
.Кроме этого, избегайте любого символа, который не является буквенно-цифровым, это безопаснее. Я не знаю ни одного окончательного списка.
Страницы руководства перечисляют их все где-то, но не в одном месте. Учите язык, это способ быть уверенным.
Тот , который поймал меня есть
!
. Это специальный символ (расширение истории) в Bash (и csh), но не в оболочке Korn. Дажеecho "Hello world!"
дает проблемы. Использование одинарных кавычек, как обычно, удаляет особое значение.источник
sed
хороша проверка с помощью , чтобы увидеть, нужно ли ее избежать. Спасибо за Ваш ответ!sed
не нужно, вы можете проверить практически с чем угодно.sed
это не проблема,bash
есть. Внутри одинарных кавычек нет специальных символов (кроме одинарных), вы даже не можете экранировать символы.sed
Команда должна обычно находиться внутри одинарных кавычек , потому что RE метасимволы имеют слишком много совпадений с метасимволами , чтобы быть безопасными. Исключением является встраивание переменных оболочки, что необходимо делать осторожно.echo
. Если вы получаете то, что положили, от него не нужно бежать. :)Я предполагаю, что вы говорите о струнах bash. Существуют разные типы строк, которые имеют разные требования к экранированию. например. Строки в одинарных кавычках отличаются от строк в двойных кавычках.
Лучшим справочником является раздел цитирования руководства по bash.
Это объясняет, каких персонажей нужно убежать. Обратите внимание, что некоторым символам может потребоваться экранирование в зависимости от того, какие опции включены, например, расширение истории.
источник
Я заметил, что bash автоматически экранирует некоторые символы при использовании автозаполнения.
Например, если у вас есть каталог с именем
dir:A
, bash автоматически завершитdir\:A
Используя это, я провел несколько экспериментов с использованием символов таблицы ASCII и вывел следующие списки:
Символы, которые удаляются через bash при автозаполнении : (включает пробел)
Символы, которые bash не избежать :
(Я исключил
/
, так как его нельзя использовать в именах каталогов)источник
printf %q
изменяют, а какие не изменяют, если передаются в качестве аргумента - в идеале, проходя весь набор символов.