最新的grep 3.8对用反斜杠转义空格的模式发出警告
$ grep "bla\ bazz" t
/tmp/bin/grep: warning: stray \ before white space
...
而 grep 3.6 则不会抱怨。处理这种模式的正确方法是什么?就是不逃离空间? IE
$ grep "bla bazz" t
是否有一些更奇特的grep
s 会错误地处理未转义的空间?也许,使用不同的配额来使一切变得漂亮和干净?
答案1
空格字符在正则表达式中并不特殊(除了启用perl
该标志时的 -like 表达式x
),因此不得转义。\
后跟空格会在 POSIX 正则表达式中产生未指定的结果。
所以你要:
grep 'blah bazz'
如果你想让它更明显,你可以使用:
grep 'blah[ ]bazz'
更一般地,您不应该将\
is 放在不是正则表达式运算符的字符前面。其中X
不是正则表达式运算符,\X
很可能是,如果现在不是,也许在未来的版本中。例如,+
, <
,d
不是基本的正则表达式运算符,但\<
,\+
和\d
用于某些grep
实现。
您可能需要\
在以下位置使用后跟空格:
grep -P '(?x) foo \ bar'
perl -ne 'print if / foo \ bar /x'
foo bar
当x
标志打开时进行匹配。但即使这样,您还是希望这样做:
grep -P '(?x) foo [ ] bar'
为了使其更易读。该标志的全部目的x
是使正则表达式更清晰,例如:
perl -ne 'print if m{
\d{4} # year
- \d{2} # month
- \d{2} # day
[ ] (foo | bar | baz)}x'
与
perl -ne'print if/\d{4}-\d{2}-\d{2} (foo|bar|baz)/'
不过,您不能[ ]
与xx
标志一起使用(在 perl 5.26+ 中,而不是 PCRE),其中括号表达式内的空格也会被忽略。
perldoc perlre
有关perl 正则表达式和man pcrepattern
PCRE(perl 兼容正则表达式)的详细信息,请参阅参考资料。使用\Q \E
是另一种选择。
无论如何,虽然空格在 shell 语法中是特殊字符,但在正则表达式中不是,但有许多字符在两者中都是特殊字符,例如*
, \
, (
, )
, ?
, , $
, ^
, [
, ]
, 因此需要转义对于这两个 if 意味着按字面匹配,最好对 shell 加上引号,并用\
(或[...]
,或者\Q...\E
在类似 perl 的情况下)来表示正则表达式。
由于\
和$
在正则表达式中很常见,并且这些字符对于双引号内的 shell 来说仍然是特殊的,因此将正则表达式放在单引号而不是双引号中是一个好习惯。仅当您需要将 shell 参数扩展到正则表达式中grep "^$var"
或需要'
在正则表达式中包含 a 时,才需要使用双引号。
与grep
正则表达式相反的文字字符串,或者换句话说,转义每一个正则表达式运算符,您可以使用-F
(for F
fixed string) 选项grep
。例如:
grep -F 'blah\ bazz'
将查找包含blah\ bazz
.
答案2
你只需要转义一个空格来保护它免受 shell 的影响,而不是为了grep
.空格字符对于正则表达式来说并不特殊,它们仅在 shell 中特殊,因为它们是 shell 用于定义参数的字符。因此,如果您的模式未加引号(这是一个坏主意),则您需要空间:
$ echo 'foo bar' | grep -c foo\ bar
1
这确保了她的 shell 不会解析foo bar
为两个参数,将其bar
作为文件名传递给grep
.您可以通过以下方式查看此操作的实际效果set -x
:
$ set -x
$ echo 'foo bar' | grep -c foo\ bar
+ grep -c 'foo bar'
+ echo 'foo bar'
1
如果你不逃跑,你会得到:
$ echo 'foo bar' | grep -c foo bar
+ grep -c foo bar
+ echo 'foo bar'
grep: bar: No such file or directory
但是,如果您引用您的模式,这将保护它免受 shell 的影响,并且不需要转义:
$ echo 'foo bar' | grep -c "foo bar"
+ grep --color -c 'foo bar'
+ echo 'foo bar'
1
或者
$ echo 'foo bar' | grep -c 'foo bar'
+ grep --color -c 'foo bar'
+ echo 'foo bar'
1
这就是为什么现在当它在空格之前grep
看到文字(引用)时会警告您:它警告您刚刚变成\
\
(空格),因为没有什么可以转义,因此
\
毫无意义。当它不是“可转义”时,它会对转义的任何其他字符执行相同的操作:
$ echo 'foo bar' | grep -c "f\oo\ bar"
+ grep --color -c 'f\oo\ bar'
+ echo 'foo bar'
grep: warning: stray \ before o
grep: warning: stray \ before white space
1
答案3
从 3.8 发行说明开始(https://savannah.gnu.org/news/?id=10191):
带有杂散反斜杠的正则表达式现在会导致警告,因为
它们的未指定行为可能会导致意外结果。例如,'\a' 和 'a' 并不总是等价的
https://bugs.gnu.org/39678。同样,
以重复运算符开头的正则表达式或子表达式现在也会
由于其未指定的行为而导致警告;例如,*a(+b|{1}c)
现在有三个警告原因。这些警告旨在作为
过渡帮助;它们在未来的版本中可能会出现错误。