В Bash, при указании аргументов командной строки для команды, какие символы необходимо экранировать?
Они ограничиваются метасимволами Баша: пробел, табуляция
|, &, ;, (, ), <, и >?
В Bash, при указании аргументов командной строки для команды, какие символы необходимо экранировать?
Они ограничиваются метасимволами Баша: пробел, табуляция
|, &, ;, (, ), <, и >?
Ответы:
Следующие символы имеют особое значение для самой оболочки в некоторых контекстах и, возможно, должны быть экранированы в аргументах:
` Backtick (U + 0060 Могильный Акцент)~ Тильда (U + 007E)! Восклицательный знак (U + 0021)# Хеш (U + 0023 числовой знак)$ Знак доллара (U + 0024)& Амперсанд (U + 0026)* Звездочка (U + 002A)( Левая скобка (U + 0028)) Правая скобка (U + 0029) ( ⇥) Вкладка (U + 0009){ Левая скобка (U + 007B Левая фигурная скобка)[ Левая квадратная скобка (U + 005B)| Вертикальная черта (вертикальная линия U + 007C)\ Обратная косая черта (U + 005C обратный солидус); Точка с запятой (U + 003B)' Одиночная кавычка / Апостроф (U + 0027)" Двойная кавычка (U + 0022)↩ Новая линия (U + 000A)< Менее чем (U + 003C)> Больше чем (U + 003E)? Вопросительный знак (U + 003F) Пробел (U + 0020) 1Некоторые из этих символов используются для большего количества вещей и в большем количестве мест, чем тот, который я связал.
Есть несколько угловых случаев, которые явно необязательны:
!может быть отключен с помощью set +H, который является значением по умолчанию в неинтерактивных оболочках.{можно отключить с помощью set +B.*и ?может быть отключен с помощью set -fилиset -o noglob .=Знак равенства (U + 003D) также необходимо экранировать, если set -kилиset -o keyword включено.Выход из новой строки требует цитирования - обратная косая черта не сработает. Любые другие символы, перечисленные в IFS , требуют аналогичной обработки. Вам не нужно бежать ]или }, но вам действительно нужно бежать , )потому что это оператор.
Некоторые из этих персонажей имеют более жесткие ограничения на то, когда им действительно нужно убежать, чем другим. Например, a#bэто нормально, но a #bэто комментарий, в то время как >в обоих контекстах нужно будет экранировать. В любом случае, избежать их всех консервативно, и это легче, чем помнить тонкие различия.
Если имя команды сама оболочка ключевое слово ( if, for, do) , то вам нужно бежать или процитировать его тоже. Единственный интересный из них in, потому что не очевидно, что это всегда ключевое слово. Вам не нужно делать это для ключевых слов, используемых в аргументах, только когда вы (по глупости!) Назвали команду в честь одного из них. Операторы оболочки ( (и &т. Д.) Всегда должны заключать в кавычки, где бы они ни находились.
1 Стефан отметил, что любой другой однобайтовый пустой символ из вашей локали также нуждается в экранировании. В большинстве распространенных, разумных локалей, по крайней мере, основанных на C или UTF-8, это только пробельные символы выше. В некоторых локалях ISO-8859-1 пространство без перерывов U + 00A0 считается пустым, включая Solaris, BSD и OS X (я думаю, что это неправильно). Если вы имеете дело с произвольной неизвестной локалью, это может включать что угодно, включая буквы, так что удачи.
Возможно, один многобайтовый символ, который считается пустым, может появиться в многобайтовом символе, который не является пустым, и у вас не будет никакого способа избежать этого, кроме как поместить все это в кавычки. Это не теоретическая проблема: в приведенном выше стандарте ISO-8859-1 этот A0байт, который считается пустым, может появляться в многобайтовых символах, таких как UTF-8, закодированный как «à» ( C3 A0). Чтобы безопасно обрабатывать эти символы, вам нужно их процитировать "à". Это поведение зависит от конфигурации локали в среде, в которой выполняется скрипт, а не от той, в которой вы его написали.
Я думаю, что это поведение нарушается несколькими способами, но мы должны разыграть ту руку, с которой имеем дело. Если вы работаете с любым несамосинхронизирующимся многобайтовым набором символов, самым безопасным будет процитировать все. Если вы в UTF-8 или C, вы в безопасности (на данный момент).
!режима ожидания только при включенном расширении истории csh, как правило, не в сценариях. [ ! -f a ]или find . ! -name...в порядке. Это описано в разделе «Более жесткие ограничения», но, возможно, стоит упомянуть об этом явно.
hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]], регулярное выражение операторы [[ x =~ ".+[" ]]. Другие ключевые слова , чем {( if, while, for...) должны быть указаны таким образом , они не признаются в качестве таковых ...
]), поэтому я не буду перечислять их. Я не думаю, что любое ключевое слово нуждается в цитировании в позиции аргумента.
В GNU Parallel это тестируется и широко используется:
$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'
$a =~ s/[\n]/'\n'/go;
Он испытан в bash, dash, ash, ksh, zsh, и fish. Некоторые персонажи не нуждаются в цитировании в некоторых (версиях) оболочек, но вышеописанное работает во всех протестированных оболочках.
Если вам просто нужна строка в кавычках, вы можете передать ее в parallel --shellquote:
printf "&*\t*!" | parallel --shellquote
Для облегченного экранирования в Perl я следую принципу одинарных кавычек. Строка Bash в одинарных кавычках может содержать любой символ, кроме самой одинарной кавычки.
Мой код:
my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";
} else {
print $_;
}
}
Пример прогона 1:
$ echo -n "abc" | perl escape_bash_special_chars.pl
abc
Пример прогона 2:
echo "abc" | perl escape_bash_special_chars.pl
'abc
'
Пример прогона 3:
echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c
Пример прогона 4:
echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'
Пример прогона 5:
echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'
echo 'ab'"'"'c'
ab'c