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 как одно из них, используйте вместо этого одинарные кавычки .


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



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включить это поведение, так что цитирование - самый безопасный ответ.
— Фил П
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.