grep : '+' 特殊字符

grep : '+' 特殊字符

我用 grep '+' 和 '*' 特殊字符做了一些简单的测试

$ echo 'where wh+'> /tmp/toto
$ grep 'wh[e]\*' /tmp/toto
$ grep 'wh[e]*' /tmp/toto
where wh+
$ grep 'wh[e]+' /tmp/toto
$ grep 'wh+' /tmp/toto
$ grep 'wh[e]\+' /tmp/toto
where
$ grep -E 'wh[e]*' /tmp/toto
where wh+
$ grep -E 'wh[e]+' /tmp/toto
where wh+

从这些测试中,非扩展 grep '+'(和 '?')不会被解释为特殊字符,为了将其用作特殊字符,必须对其进行转义。据我所知,grep 使用基本正则表达式(不带 -E 选项),在这种情况下,特殊字符在这里定义: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03 和 '?' “+”不是 BRE 的特殊字符。

但是为什么在 BRE 中转义非特殊字符“+”会使其成为特殊字符呢?

答案1

这是一个 GNU 扩展。来自grep(1)联机帮助页:

在 GNU 中grep,基本语法和扩展语法之间的可用功能没有区别。在其他实现中,基本正则表达式的功能不太强大。以下描述适用于扩展正则表达式;随后总结了基本正则表达式的差异。

再往下

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

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

答案2

在您提供的 POSIX 规范的链接中,您可以阅读:

普通字符是与自身匹配的 BRE:受支持的字符集中的任何字符,BRE 特殊字符中列出的 BRE 特殊字符除外。

前面带有 ( '\' ) 的普通字符的解释是未定义的,除了:

  • 字符“)”、“(”、“{”和“}”
  • 数字 1 到 9(含)(请参阅匹配多个字符的 BRE)
  • 括号表达式内的字符

所以基本上,由于+是一个普通的 BRE 字符,因此 的行为grep 'x\+'是未指定的,一些实现(例如 GNU)将其视为与( )grep相同,有些与某些可能视为相同或其他任何东西相同。grep 'x\{1,\}'grep -E 'x+'grep 'x+'grep 'x\\+'

因此,如果您打算可移植地匹配字符串x\+,则应该编写grep 'x\\+'(or grep 'x[\]+', or grep -F 'x\+'or grep -E 'x\\\+'or grep -E 'x[\][+]')。

答案3

我不太明白上面的哪个示例对您来说似乎违反了定义的行为?

+ 的转义不会改变规则。

相关内容