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

17

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

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

这不对吧。为什么我需要转义花括号,而不是方括号等作为“匹配前面的N次”组件的一部分时呢?

难道只有当我编写一个实际匹配查询字符串中的 {} 字符的正则表达式时才需要转义吗?

这更像是情感宣泄,但我很好奇答案。


建议您查看以下网址:http://www.grymoire.com/Unix/Grep.html 和 http://www.grymoire.com/Unix/Regular.html。 - Jason Hu
3个回答

20

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

你可以像你所做的那样进行转义:

$ 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,见下文)。(POSIX规定了-E。)

...

正则表达式

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

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

...

基本正则表达式与扩展正则表达式

在基本正则表达式中,元字符“?”,“+”,“{”,“|”,“(”和“)”失去其特殊含义;而需要使用反斜杠版本 \?\+\{\|\(\)


1
如果我包含了手册中的解释而不是自己编写,那么就可以节省很多按键操作! - Tom Fenech
我收到了一个踩,不确定原因。如果是因为缺乏解释,那是因为我正在更新 :) - fedorqui
@Tom Fenech 我更喜欢参考“man”页面,我不擅长高速书写好的英语 :) - fedorqui
是的,那很有道理。这绝对不是批评! :) - Tom Fenech

8
答案涉及基本正则表达式(BRE)和扩展正则表达式(ERE)之间的区别。
  • 在BRE模式下(即在调用grep而不指定其他参数时),{}会被解释为字面字符。通过使用\来转义它们,这意味着它们应该被解释为前一个模式的实例数。

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


1
相反,请这样做。
echo '@NS500287' | egrep '^@NS500[0-9]{3}'
#                  ^
#                 /
#       notice ---

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接