В 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