Grep和正则表达式 - 为什么我要逃避花括号?

时间:2014-11-06 15:30:51

标签: regex bash shell grep escaping

我对grep似乎解析正则表达式的方式感到非常困惑:

$ echo "@NS500287" | grep '^@NS500[0-9]{3}'
#nothing
$ echo "@NS500287" | grep '^@NS500[0-9]\{3\}'
@NS500287

这不可能是正确的。为什么我要转义大括号,它是“匹配前一个,N次”组件的一部分(而不是,例如方括号)?

只有当我在查询字符串中编写一个实际上与{}匹配的正则表达式时才应该转义吗?

更多的 cri de coeur 比其他任何事情更多,但我对答案感到好奇。

3 个答案:

答案 0 :(得分:14)

这是因为{}是特殊字符,需要以不同方式处理才能具有此特殊行为。否则,它们将被视为文字{}

你可以像你一样逃避:

$ echo "@NS500287" | grep '^@NS500[0-9]\{3\}'
@NS500287

或使用grep -E

$ echo "@NS500287" | grep -E '^@NS500[0-9]{3}'
@NS500287

没有任何处理:

$ echo "he{llo" | grep "{"
he{llo

来自man grep

  

-E , - extended-regexp

     

将PATTERN解释为扩展正则表达式(ERE,见下文)。   (-E由POSIX指定。)

     

...

     

正常表达

     

正则表达式是描述一组字符串的模式。   正则表达式的构造类似于算术   表达式,通过使用各种运算符来组合较小的   表达式。

     

grep了解正则表达式的三种不同版本   语法:“基本”,“扩展”和“perl。”在GNU grep中,有   基本和扩展之间的可用功能没有区别   语法。在其他实现中,基本正则表达式是   不那么强大。以下描述适用于扩展常规   表达式;总结了基本正则表达式的差异   然后。 Perl正则表达式提供了额外的功能,   并记录在pcresyntax(3)和pcrepattern(3)中,但可能不是   可在每个系统上使用。

     

...

     

基本与扩展正则表达式

     

在基本正则表达式中,元字符?,+,{,|,(和)失去了它们的特殊含义;而是使用反斜杠版本\?\+\{\|\(\)

答案 1 :(得分:6)

答案与基本正则表达式(BRE)和扩展正则表达式(ERE)之间的区别有关。

  • 在BRE模式下(即当您调用grep时没有参数指定其他情况),{}被解释为文字字符。使用\转义它们意味着它们将被解释为先前模式的多个实例。

  • 如果您使用grep -E代替(ERE模式),您可以使用{}而无需转义以引用计数。在ERE模式下,转义大括号会导致它们被字面解释。

答案 2 :(得分:0)

取而代之的是

echo '@NS500287' | egrep '^@NS500[0-9]{3}'
#                  ^
#                 /
#       notice ---