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

bash:如何传递包含特殊字符的命令行参数?

我自己写了一个linux程序program,需要一个正则表达式作为输入。

我想在bash的shell中调用程序,并将这个正则表达式作为命令行参数传给程序(还有其他命令行参数)。一个典型的正则表达式看起来像

[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]")。

编辑:正如一些所指出的,dobleqouting并不阻止变量扩展或命令替换。因此,如果你的regex中包含了一些可以被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

man bash

有三种引号机制:escape字符、单引号和双引号。

非引号的反斜杠 ( ** ) 是 _escape 字符。它保留了下一个字符的字面值,但<新行>除外。如果出现了一个*的反斜线对,并且反斜线本身没有被引用,那么***的反斜线将被视为一个行的延续(也就是说,它将被从输入流中移除并被有效地忽略)。

在单引号中封闭字符会保留引号中每个字符的字面价值。单引号之间不能出现单引号,即使前面有反斜杠。

双引号中的字符保留引号内所有字符的字面价值,但$` , ** , and, when history expansion is enabled, **!. The characters $ and `在双引号内保留其特殊含义。反斜杠只有在下列字符后保留其特殊含义。$ , ` , , / , 或 /. 双引号可以通过在双引号前加反斜杠来引用。如果启用,历史扩展将被执行,除非双引号中出现的使用反斜线转义。在前面的反斜线不会被删除。

特殊参数/@用双引号表示时有特殊含义(参见下面的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_ **"** ) ,会导致该字符串根据当前的语言环境进行翻译。如果当前的locale是**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 ) ,会导致该字符串根据当前的语言环境进行翻译。如果当前的locale是CPOSIX,美元符号将被忽略。如果字符串被翻译和替换,替换的内容会被双引号。

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

尽管它作为一个regex可能没有什么用处,但一些字符序列可能被解释为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

模式从哪里来?是固定的还是来自用户?是本地系统上调用脚本的用户,还是远程的人?

你用引号来包裹数据,以防止shell解释数据。有两种选择。

1.双引号,仍然允许一些解释($expand和backticks) 2. 单引号,它允许所有的东西都通过

因为 $ 在 regexps 中是一个有效的字符(行末/缓冲区),你可能想用单引号来保存 regexp,除非你把它存储在一个变量中。如果你从不受信任的人那里获取任意数据,你需要用'代替'"'"',然后用单引号包住。

请注意,[abc]_[x|y]看起来像是要匹配xy,而实际上是在匹配三个字符中的一个xy|。方括号匹配的是里面的字符,只有-才是范围,开头的^是否定的。所以,[abc]_(x|y)可能是你的意思,而括号是shell专用的字符。方括号不是shell的特殊字符,只是看起来像。双方括号[[...]]是特殊字符。

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

转义它们应该可以正常工作:

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