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



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



в частности, я проверял, есть ли % должен быть экранирован или нет. Я пытался



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


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



и более общие: они же символы, чтобы бежать в shell и bash?

872   7  

7 ответов:

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

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

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

'I'\''m a s@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/$/"/'.

2В. Более читабельный вариант 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/$/"/'.


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

обратите внимание, что переменные оболочки определяются только для текста в смысле POSIX. Обработка двоичных данных не определена. Для реализаций, которые имеют значение, binary работает за исключением байтов NUL (поскольку переменные реализуются с помощью строк C и предназначены для использования в качестве строк C, а именно программы аргументы), но вы должны переключиться на "двоичную" локаль, такую как latin1.


(вы можете легко проверить правила, прочитав спецификацию POSIX для sh. Для bash проверьте справочное руководство, связанное с @AustinPhillips)

чтобы спасти кого-то еще от необходимости RTFM... в Баш:

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

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

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

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

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

printf [- v var] формат [аргументы]

 %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 $'2'    34 - 4          4E - N          68 - h      
01 E $'1'    1B E $'\E'      35 - 5          4F - O          69 - i      
02 E $'2'    1C E $'4'    36 - 6          50 - P          6A - j      
03 E $'3'    1D E $'5'    37 - 7          51 - Q          6B - k      
04 E $'4'    1E E $'6'    38 - 8          52 - R          6C - l      
05 E $'5'    1F E $'7'    39 - 9          53 - S          6D - m      
06 E $'6'    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 $'6'    28 E \(         42 - B          5C E \         76 - v      
0F E $'7'    29 E \)         43 - C          5D E \]         77 - w      
10 E $'0'    2A E \*         44 - D          5E E \^         78 - x      
11 E $'1'    2B - +          45 - E          5F - _          79 - y      
12 E $'2'    2C E \,         46 - F          60 E \`         7A - z      
13 E $'3'    2D - -          47 - G          61 - a          7B E \{     
14 E $'4'    2E - .          48 - H          62 - b          7C E \|     
15 E $'5'    2F - /          49 - I          63 - c          7D E \}     
16 E $'6'    30 - 0          4A - J          64 - d          7E E \~     
17 E $'7'    31 - 1          4B - K          65 - e          7F E $'7'
18 E $'0'    32 - 2          4C - L          66 - f      
19 E $'1'    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 должен быть экранирован в Баш.

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

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

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

тот, который поймал меня это !. Это специальный символ (расширение истории) в 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. Существуют различные типы строк, которые имеют различный набор требований для побега. например. Строки с одинарными кавычками отличаются от строк с двойными кавычками.

лучшая ссылка-это цитирую раздел руководства bash.

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

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

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

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

символы, которые Баш убегает на автозаполнение: (включая пробел)

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

символы, которые bash не делает побег:

#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

(Я исключил /, так как он не может быть использован в имени каталога)

Comments

    Ничего не найдено.