bash: как передать аргументы командной строки, содержащие специальные символы

31

Я написал себе программу для Linux, programкоторая нуждается в регулярном выражении в качестве входных данных.

Я хочу вызвать программу в bashоболочке и передать это регулярное выражение в качестве аргумента командной строки программе (есть и другие аргументы командной строки). Типичное регулярное выражение выглядит как

[abc]\_[x|y]

К сожалению , символы [, ]и |специальные символы в bash. Таким образом, призывая

program [abc]\_[x|y] anotheragument

не работает Есть ли способ передать выражение с помощью каких-либо escape-символов или кавычек и т. Д.?

(Вызов также program "[abc]\_[x|y] anotheragument"не работает, потому что он интерпретирует два аргумента как один.)

Кристиан
источник

Ответы:

27

Вы также можете

  1. Избегайте каждого отдельного специального символа с обратной косой чертой (как в \[abc\]_\[x\|y\]) или
  2. Двойной кавычки весь аргумент (как в "[abc]_[x|y]").

РЕДАКТИРОВАТЬ: Как некоторые уже отмечали, dobleqouting не предотвращает расширение переменных или подстановку команд. Поэтому, если ваше регулярное выражение содержит что-то, что может быть интерпретировано bash как одно из них, используйте вместо этого одинарные кавычки .

antichris
источник
4
В bash двойные кавычки не обходят расширение переменных "$HOME"или параметров "${USER:-root}", подстановку команд в форме "$(date)"или "`date`"арифметическое расширение "$((1 + 2))", расширение истории "!!"или экранирование обратной косой черты "\\". Вместо этого используйте одинарные кавычки. См. Справочную страницу руководства по bash, раздел «Цитирование».
Flimm
25

Используйте одинарные кавычки. Одинарные кавычки гарантируют, что ни один из символов не будет интерпретирован.

$ printf %s 'spaces  are  not  interpreted away
neither are new lines
nor variable names $TESTING
nor square brackets [TESTING]
nor pipe characters or redirection symbols | > <
nor the semicolon ;
nor backslashes \a \b \c \\
the only thing that does not work is the single quote itself
'

Есть два решения, если вам нужно вставить одну цитату:

$ printf '%s\n' '[ Don'"'"'t worry, be happy! ]'
[ Don't worry, be happy! ]
$ printf '%s\n' '[ Don'\''t worry, be happy! ]'
[ Don't worry, be happy! ]
Флимм
источник
Вы правы. +1
антихрис
6

в man bash

Существует три механизма цитирования: escape-символ , одинарные и двойные кавычки.

Обратная косая черта без кавычек ( \ ) является escape-символом . Он сохраняет буквальное значение следующего символа, за исключением <newline>. Если появляется пара \ <newline>, а обратная косая черта сама по себе не заключена в кавычки, \ <newline> рассматривается как продолжение строки (то есть она удаляется из входного потока и фактически игнорируется).

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

Заключение символов в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $ , ` , \ и, когда расширение истории включено ,! , Символы $ и ` сохраняют свое особое значение в двойных кавычках. Обратная косая черта сохраняет свое специальное значение только тогда, когда за ней следует один из следующих символов: $ , ` , " , \ или <newline> . Двойная кавычка может заключаться в двойные кавычки, если перед ней стоит обратная косая черта. Если включено, расширение истории будет выполняться, если! в двойных кавычках экранируется обратная косая черта. Обратная косая черта предшествует ! не удаляется.

Специальные параметры * и @ имеют особое значение в двойных кавычках (см. ПАРАМЕТРЫ ниже).

Слова вида $ ' string ' обрабатываются специально. Слово расширяется до строки , символы с обратной косой чертой заменяются в соответствии со стандартом ANSI C. Escape-последовательности с обратной косой чертой, если они есть, декодируются следующим образом:

       \      оповещение (звонок)
        \ b      возврат на      одну позицию
        \ e 
       \ E escape-символ
        \ f      перевод
             строки \ n новая строка
        \ r      возврат каретки
        \ t      горизонтальная табуляция
        \ v      вертикальная табуляция
        \\      обратная косая черта
        \ "      одинарная кавычка
        \"      двойная кавычка
        \ nnn    the восьмибитный символ, значение которого является восьмеричным значением nnn
              (от одной до трех цифр)
       \ x HH    восьмибитный символ, значение которого является шестнадцатеричным значением HH
              (одна или две шестнадцатеричные цифры)
       \ u HHHH символ Unicode (ISO / IEC 10646), значение которого
              шестнадцатеричное значение HHHH (от одной до четырех шестнадцатеричных цифр)
        \ U HHHHHHHH
              символ Unicode (ISO / IEC 10646), значение которого
              шестнадцатеричное значение HHHHHHHH (от одной до восьми шестнадцатеричных цифр)
        \ c x     контрольный символ x

Расширенный результат заключен в одинарные кавычки, как если бы знак доллара отсутствовал.

Строка в двойных кавычках, перед которой стоит знак доллара ( $ " string " ), приведет к переводу строки в соответствии с текущей локалью. Если текущим языковым стандартом является C или POSIX , знак доллара игнорируется. Если строка переведена и заменена, замена заменяется двойными кавычками.

Эван Кэрролл
источник
2

Вы можете использовать обратную косую черту ( \) перед специальными символами, чтобы экранировать их следующим образом:

Джон @ Круто: ~ # Эхо \ &
&
Джон Т
источник
2

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

program '[abc]_[x|y]' anotherargument

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

param_array=('[abc]_[x|y]' anotherargument)    # create an array
param_array+=(yetanother)     # append another element to the array
program "${param_array[@]}"   # use the array elements as arguments to program
Приостановлено до дальнейшего уведомления.
источник
1
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
Витек
источник
0

Побег из них должен работать нормально:

  programm \[abc\]_\[x\|y\]
Бобби
источник
0

Откуда взялся этот паттерн? Это исправлено или от пользователя? Это пользователь, который вызывает скрипт в локальной системе, или кто-то удаленный?

Вы используете кавычки для переноса данных, чтобы оболочка не интерпретировала их. Есть два варианта:

  1. Двойные кавычки, которые все еще допускают некоторую интерпретацию ($ expand и `backticks`)
  2. Одиночные кавычки, которые пропускают все буквально

Поскольку $в регулярных выражениях допустимый символ (конец строки / буфер), вы, вероятно, захотите использовать одинарные кавычки для хранения регулярного выражения, если только вы не храните в переменной. Если вы принимаете произвольные данные от кого - то ненадежного, вам необходимо заменить 'с , '"'"'а затем завернуть в одинарных кавычках.

Обратите внимание, что [abc]_[x|y]похоже, что вы хотите соответствовать xили y, в то время как это на самом деле соответствует одному из трех символов xy|. Квадратные скобки соответствуют символам внутри и только -для диапазонов и a ^в начале для отрицания. Таким образом, это [abc]_(x|y)может быть то, что вы имели в виду, а круглые скобки - это символы, которые являются специальными для оболочки. Квадратные скобки не являются особенными для оболочки, это выглядит так, как будто они есть. Двойные квадратные скобки [[ ... ]]являются специальными.

Фил П
источник
Это один из самых правильных ответов здесь (я особенно ценю инструкцию по замене 'на '"'"'), однако он все еще не верен. [Это специальный символ для оболочки, он используется в подстановочных знаках при расширении пути (что делает оболочку для всего, что не заключено в кавычки).
jpalecek
Это особенное в некоторых контекстах, таких как подписка на переменные или глобализация, но вы все равно можете набрать, foo=a[b]а затем echo $fooи увидеть, что строка не нуждается в кавычках. Вы правы, я был слишком краток.
Фил П,
Если вам не повезло, abв текущем каталоге есть файл , который fooбудет содержать abвместо a[b]. Процитируйте свои квадратные скобки, люди.
Клак
(Для ясности: я делаю цитату (как было ясно из первоначального ответа, где я настаивал на цитировании), и это боковая крушение, к которой я обращаюсь). Это утверждение удивило меня, поэтому я проверил его. Это не верно в zsh или bash, но верно в BSD / bin / sh. Это против POSIX и является нестандартным поведением, так что вам нужно будет процитировать его для обработки. В zsh вы также можете setopt glob_assignвключить это поведение, так что цитирование - самый безопасный ответ.
Фил П