Какие символы нужно избегать при использовании Bash?

Есть ли какой-либо исчерпывающий список символов, которые должны быть экранированы в Bash? Можно ли это проверить только с sed ?

В частности, я проверял, нужно ли бежать или нет. Я пытался

 echo "h%h" | sed 's/%/i/g' 

и работал нормально, не избегая % . Означает ли это, что % не нужно избегать? Это хороший способ проверить необходимость?

И более общий: они одни и те же персонажи, чтобы убежать в shell и bash ?

7 Solutions collect form web for “Какие символы нужно избегать при использовании Bash?”

Существует два простых и безопасных правила, которые работают не только в sh но и в bash .

1. Поместите всю строку в одинарные кавычки

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

 'I'\''mas@fe $tring which ends in newline ' 

sed: sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"

2. Побег каждого символа с обратной косой чертой

Это работает для всех символов, кроме новой строки. Для символов новой строки используются одиночные или двойные кавычки. Пустые строки все равно должны обрабатываться – заменить на ""

 \I\'\m\ \a\ \s\@\f\e\ \$\t\r\i\n\g\ \w\h\i\c\h\ \e\n\d\s\ \i\n\ \n\e\w\l\i\n\e" " 

команда sed: sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' .

2b. Более читаемая версия 2

Существует простой безопасный набор символов, например [a-zA-Z0-9,._+:@%/-] , который может быть оставлен без сохранения, чтобы он был более читабельным.

 I\'m\ a\ s@fe\ \$tring\ which\ ends\ in\ newline" " 

Команда sed: LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' 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)

Чтобы спасти кого-то еще от RTFM … в bash :

Закрывающиеся символы в двойных кавычках сохраняют буквальное значение всех символов внутри кавычек, за исключением $ , ` , \ , и, когда расширение истории включено ! ,

… так что, если вы избежите этих (и, собственно, и цитаты, конечно), вы, вероятно, все в порядке.

Если вы придерживаетесь более консервативного подхода «когда сомневаетесь, избегайте его», следует избегать использования символов с особым значением, не избегая символов-идентификаторов (например, букв ASCII, цифр или «_»). Очень маловероятно, что они когда-либо (то есть в какой-то странной оболочке POSIX-ish) имеют особое значение и, следовательно, должны быть экранированы.

формат, который может быть повторно использован как ввод оболочки

Для этого типа запроса существует специальная директива формата printf ( %q ):

printf [-v var] format [arguments]

  %q causes printf to output the corresponding argument in a format that can be reused as shell input. 

Некоторые образцы:

 read foo Hello world printf "%q\n" "$foo" Hello\ world printf "%q\n" $'Hello world!\n' $'Hello world!\n' 

Это также можно использовать с помощью переменных:

 printf -v var "%q" "$foo " echo "$var" $'Hello world\n' 

Быстрая проверка со всеми (128) байтами ascii:

Обратите внимание, что все байты от 128 до 255 должны быть экранированы.

 for i in {0..127} ;do printf -v var \\%o $i printf -v var $var printf -v res "%q" "$var" esc=E [ "$var" = "$res" ] && esc=- printf "%02X %s %-7s\n" $i $esc "$res" done | column 

Это должно выглядеть примерно так:

 00 E '' 1A E $'\032' 34 - 4 4E - N 68 - h 01 E $'\001' 1B E $'\E' 35 - 5 4F - O 69 - i 02 E $'\002' 1C E $'\034' 36 - 6 50 - P 6A - j 03 E $'\003' 1D E $'\035' 37 - 7 51 - Q 6B - k 04 E $'\004' 1E E $'\036' 38 - 8 52 - R 6C - l 05 E $'\005' 1F E $'\037' 39 - 9 53 - S 6D - m 06 E $'\006' 20 E \ 3A - : 54 - T 6E - n 07 E $'\a' 21 E \! 3B E \; 55 - U 6F - o 08 E $'\b' 22 E \" 3C E \< 56 - V 70 - p 09 E $'\t' 23 E \# 3D - = 57 - W 71 - q 0A E $'\n' 24 E \$ 3E E \> 58 - X 72 - r 0B E $'\v' 25 - % 3F E \? 59 - Y 73 - s 0C E $'\f' 26 E \& 40 - @ 5A - Z 74 - t 0D E $'\r' 27 E \' 41 - A 5B E \[ 75 - u 0E E $'\016' 28 E \( 42 - B 5C E \\ 76 - v 0F E $'\017' 29 E \) 43 - C 5D E \] 77 - w 10 E $'\020' 2A E \* 44 - D 5E E \^ 78 - x 11 E $'\021' 2B - + 45 - E 5F - _ 79 - y 12 E $'\022' 2C E \, 46 - F 60 E \` 7A - z 13 E $'\023' 2D - - 47 - G 61 - a 7B E \{ 14 E $'\024' 2E - . 48 - H 62 - b 7C E \| 15 E $'\025' 2F - / 49 - I 63 - c 7D E \} 16 E $'\026' 30 - 0 4A - J 64 - d 7E E \~ 17 E $'\027' 31 - 1 4B - K 65 - e 7F E $'\177' 18 E $'\030' 32 - 2 4C - L 66 - f 19 E $'\031' 33 - 3 4D - M 67 - g 

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

Почему?

Вы могли видеть некоторые символы, которые не всегда должны быть экранированы, например } и { .

Поэтому не всегда, а когда-то :

 echo test 1, 2, 3 and 4,5. test 1, 2, 3 and 4,5. 

или

 echo test { 1, 2, 3 } test { 1, 2, 3 } 

но уход:

 echo test{1,2,3} test1 test2 test3 echo test\ {1,2,3} test 1 test 2 test 3 echo test\ {\ 1,\ 2,\ 3\ } test 1 test 2 test 3 echo test\ {\ 1\,\ 2,\ 3\ } test 1, 2 test 3 

Символы, которые требуют экранирования, различны в Bourne или POSIX, чем Bash. Обычно (очень) Bash является надмножеством этих оболочек, поэтому все, что вы выходите в shell должно быть экранировано в Bash.

Хорошим общим правилом было бы «если в сомнении, избегайте его». Но экранирование некоторых символов дает им особое значение, например \n . Они перечислены на страницах man bash разделе Quoting and echo .

Помимо этого, избегайте любого символа, который не является буквенно-цифровым, это безопаснее. Я не знаю ни одного окончательного списка.

Страницы руководства перечисляют их где-то, но не в одном месте. Изучите язык, это способ быть уверенным.

Тот, кто меня поймал ! , Это особый символ (расширение истории) в Bash (и csh), но не в оболочке Korn. Даже echo "Hello world!" дает проблемы. Использование одиночных кавычек, как обычно, устраняет особое значение.

Используя технику print '%q' , мы можем запустить цикл, чтобы узнать, какие символы являются специальными:

 #!/bin/bash special=$'`!@#$%^&*()-_+={}|[]\\;\':",.<>?/ ' for ((i=0; i < ${#special}; i++)); do char="${special:i:1}" printf -v q_char '%q' "$char" if [[ "$char" != "$q_char" ]]; then printf 'Yes - character %s needs to be escaped\n' "$char" else printf 'No - character %s does not need to be escaped\n' "$char" fi done | sort 

Он дает этот результат:

 No, character % does not need to be escaped No, character + does not need to be escaped No, character - does not need to be escaped No, character . does not need to be escaped No, character / does not need to be escaped No, character : does not need to be escaped No, character = does not need to be escaped No, character @ does not need to be escaped No, character _ does not need to be escaped Yes, character needs to be escaped Yes, character ! needs to be escaped Yes, character " needs to be escaped Yes, character # needs to be escaped Yes, character $ needs to be escaped Yes, character & needs to be escaped Yes, character ' needs to be escaped Yes, character ( needs to be escaped Yes, character ) needs to be escaped Yes, character * needs to be escaped Yes, character , needs to be escaped Yes, character ; needs to be escaped Yes, character < needs to be escaped Yes, character > needs to be escaped Yes, character ? needs to be escaped Yes, character [ needs to be escaped Yes, character \ needs to be escaped Yes, character ] needs to be escaped Yes, character ^ needs to be escaped Yes, character ` needs to be escaped Yes, character { needs to be escaped Yes, character | needs to be escaped Yes, character } needs to be escaped 

Некоторые из результатов, например , выглядят немного подозрительно. Было бы интересно получить данные @ CharlesDuffy об этом.

Я предполагаю, что вы говорите о струнах bash. Существуют различные типы строк, которые имеют различный набор требований к экранированию. например. Строки одиночных кавычек отличаются от строк с двойными кавычками.

Наилучшей ссылкой является раздел Quoting руководства bash.

Он объясняет, какие символы нужно ускользать. Обратите внимание, что некоторым символам может потребоваться экранирование в зависимости от того, какие опции включены, например, расширение истории.

Я заметил, что при использовании автозаполнения bash автоматически ускользает от некоторых символов.

Например, если у вас есть каталог с именем dir:A , bash будет автоматически завершен до dir\:A

Используя это, я провел несколько экспериментов с использованием символов таблицы ASCII и получил следующие списки:

Символы, которые bash выходят из автозаполнения : (включает пробел)

  !"$&'()*,:;< =>?@[\]^`{|} 

Персонажи, которые bash не убегают :

 #%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ 

(Я исключал / , поскольку его нельзя использовать в именах каталогов)

Interesting Posts

Выберите , который href заканчивается некоторой строкой

Проверьте, указывает ли указатель на выделенную память в куче

Удаленный рабочий стол: масштаб и полный экран – как? (Удаленные Win10, Win7, 2008 и 2003 хосты)

Почему структуры хранятся в стеке, а classы хранятся в куче (.NET)?

Excel для подсчета количества одновременных сеансов в зависимости от времени начала и окончания

Найти строку текста в элементе и обернуть вокруг него tags span

Архивирование проекта в Xcode неправильно создает пакет из нескольких приложений

Как я могу перебирать все флажки в форме?

Как загрузить многостраничные данные и изображение на сервер в Android?

Как изменить символ для десятичной точки в double.ToString ()?

Измерьте время выполнения для Java-метода

Стэнфордский Wrangler идеален, но налагает ограничения, какие другие варианты?

Как найти наименьшее число с 0 и 1, которое делится на заданный номер?

вставить запрос с последовательным первичным ключом

используя class, определенный в dll c ++ в коде c #

Давайте будем гением компьютера.