Не забудьте (возможно), что имя файла отображается с * и?
Джефф Шаллер
Благодарю. Не могли бы вы исчерпывающе перечислить виды символов, которые должны быть экранированы в аргументах строки cmd?
Тим
Список полезен, но самое важное, что нужно понимать при цитировании: все, что между одинарными кавычками, передается буквально и без разделения слов. Без исключений. (Между прочим, это означает, что нет никакого способа вставить одинарную кавычку в одинарные кавычки, но это легко обойти .)
Wildcard
Ответы:
22
Следующие символы имеют особое значение для самой оболочки в некоторых контекстах и, возможно, должны быть экранированы в аргументах:
=Знак равенства (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...) должны быть указаны таким образом , они не признаются в качестве таковых ...
Stephane Chazelas
Если это вообще аргументы командной строки, то интерпретация зависит от рассматриваемой команды (как и я ]), поэтому я не буду перечислять их. Я не думаю, что любое ключевое слово нуждается в цитировании в позиции аргумента.
Майкл Гомер
2
Цитирование встроенных, тире или% ничего не делает.
Майкл Гомер
3
В GNU Parallel это тестируется и широко используется:
Он испытан в bash, dash, ash, ksh, zsh, и fish. Некоторые персонажи не нуждаются в цитировании в некоторых (версиях) оболочек, но вышеописанное работает во всех протестированных оболочках.
Если вам просто нужна строка в кавычках, вы можете передать ее в parallel --shellquote:
@ TomH будет признателен, если вы сможете потратить 5 минут на размышления о том, как мы могли бы с вами связаться.
Оле Танге
Я думаю, что это проблема прогресса. большинство людей не нуждаются или не понимают параллели, пока не пройдут некоторые стадии сложности. К этому времени они встретили xargs, nohup и все в таком духе. Кроме того, я не вижу много людей, использующих параллель для решения проблем в обмене стека или когда я ищу в Google решения для решения проблем
Tom H
1
Для облегченного экранирования в Perl я следую принципу одинарных кавычек. Строка Bash в одинарных кавычках может содержать любой символ, кроме самой одинарной кавычки.
Мой код:
my $bash_reserved_characters_re = qr([!"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";}else{
print $_;}}
Да, верный момент, который. Я считаю, что большинство людей попадут на эту страницу, потому что у них есть проблема, которую нужно решить. Не потому, что это делает интересные академические дебаты. Вот почему я хотел бы предложить решения и обсудить их достоинства, хотя и немного не по теме.
Яри Туркиа
Мой код - просто реализация ответа Майкла Гомера. Я не собирался приносить больше информации, чем то, что он сделал.
Ответы:
Следующие символы имеют особое значение для самой оболочки в некоторых контекстах и, возможно, должны быть экранированы в аргументах:
`
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 это тестируется и широко используется:
Он испытан в
bash
,dash
,ash
,ksh
,zsh
, иfish
. Некоторые персонажи не нуждаются в цитировании в некоторых (версиях) оболочек, но вышеописанное работает во всех протестированных оболочках.Если вам просто нужна строка в кавычках, вы можете передать ее в
parallel --shellquote
:источник
Для облегченного экранирования в Perl я следую принципу одинарных кавычек. Строка Bash в одинарных кавычках может содержать любой символ, кроме самой одинарной кавычки.
Мой код:
Пример прогона 1:
Пример прогона 2:
Пример прогона 3:
Пример прогона 4:
Пример прогона 5:
источник