2010-07-14 12:51:58 +0000 2010-07-14 12:51:58 +0000
32
32

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

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

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

[abc]\_[x|y]

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

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

не работает. Есть ли способ передать выражение, используя какие-то экранирующие символы, кавычки и т.д.?

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

Ответы (8)

29
29
29
2010-07-14 12:59:46 +0000

Вы можете либо

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

EDIT: Как отмечают некоторые , доблекутирование не препятствует расширению переменных и подстановке команд. Поэтому, если ваш регекс содержит что-то, что может быть интерпретировано bash как одно из них, используйте одинарные кавычки вместо этого.

28
28
28
2011-10-21 12:19:50 +0000

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

$ 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!]
6
6
6
2010-07-15 06:09:18 +0000

Per man bash

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

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

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

Заключение символов в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $ , ` , ** , and, when history expansion is enabled, **!. The characters $ and ` сохраняет их особое значение в двойных кавычках. Обратный слеш сохраняет свое особое значение только в том случае, если за ним следует один из следующих символов: $ , `, *, *** или **<newline>. Двойная кавычка может быть заключена в двойные кавычки, если перед ней обратная косая черта. Если включено, расширение истории будет выполняться, если только !, появляющееся в двойных кавычках, не экранируется с помощью обратной косой черты. Обратная косая черта, предшествующая !, не удаляется.

Специальные параметры * и @ имеют особое значение при использовании в двойных кавычках (см. PARAMETERS ниже).

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

**\a** alert (bell) **\b** backspace **\e**** \E **an escape character** \f **form feed** \n **new line** \r **carriage return** \t **horizontal tab** \v **vertical tab** \ **backslash**  

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

Строка в двойных кавычках, которой предшествует знак доллара ( **$"** _string_ **"**), приведет к тому, что строка будет переведена в соответствии с текущей локалью. Если текущая локаль равна **C** или **POSIX**, знак доллара игнорируется. Если строка будет переведена и заменена, то замена будет заключена в двойные кавычки. **single quote** \" **double quote** \**_nnn_ the eight-bit character whose value is the octal value _nnn_ (one to three digits)**\x**_HH_ the eight-bit character whose value is the hexadecimal value _HH_ (one or two hex digits)**\u**_HHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHH_ (one to four hex digits)**\U**_HHHHHHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHHHHHH_ (one to eight hex digits)**\c**_x_ a control-_x_ character

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

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

2
2
2
2010-07-15 02:11:13 +0000

Хотя это может и не пригодиться в качестве регекса, некоторые последовательности символов могут быть интерпретированы как имена переменных 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
2
2
2
2010-07-14 12:57:29 +0000

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

john@awesome:~ # echo 0x1& &
1
1
1
2010-07-14 12:56:05 +0000
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
0
0
0
2010-07-15 07:18:57 +0000

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

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

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

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

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

0
0
0
2010-07-14 12:57:13 +0000

Спасение их должно работать хорошо:

programm \[abc\]_\[x\|y\]

Похожие вопросы

6
10
11
7
8