我用 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
我不太明白上面的哪个示例对您来说似乎违反了定义的行为?
+ 的转义不会改变规则。