据我所知,非贪婪匹配不是基本正则表达式(BRE)和扩展正则表达式(ERE)的一部分。然而,不同版本的grep(BSD和GNU)的行为似乎表明了相反的情况。
例如,让我们看下面的例子。我有一个字符串:
使用GNU
使用BSD
在启用
使用
例如,让我们看下面的例子。我有一个字符串:
string="hello_my_dear_polo"
使用GNU grep
:
以下是从字符串中提取hello
的几个尝试。
BRE尝试(失败):
$ grep -o "hel.*\?o" <<< "$string"
hello_my_dear_polo
输出产生了整个字符串,这表明非贪婪量词在BRE上不起作用。请注意,我仅转义了?
,因为*
不会失去其含义,也不需要转义。
ERE尝试(失败):
$ grep -oE "hel.*?o" <<< "$string"
hello_my_dear_polo
启用-E
选项也会产生相同的输出,表明非贪婪匹配不是ERE的一部分。在这里我们使用ERE,因此不需要转义。
PCRE尝试(成功):
$ grep -oP "hel.*?o" <<< "$string"
hello
启用PCRE的-P
选项表示非贪婪量词是其中的一部分,因此我们可以得到所需的hello
输出。由于我们使用的是PCRE,因此不需要转义。
使用BSD grep
:
以下是从字符串中提取hello
的几次尝试。
BRE尝试(失败):
$ grep -o "hel.*\?o" <<< "$string"
使用BRE在BSD的grep
命令中没有输出。
ERE尝试(成功):
$ grep -oE "hel.*?o" <<< "$string"
hello
在启用
-E
选项后,我很惊讶我能提取到我所需的输出。我的问题是关于我从这次尝试中得到的输出。PCRE尝试(失败):
$ grep -oP "hel.*?o" <<< "$string"
usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
使用
-P
选项给了我使用错误,这是预期的,因为 BSD 版本的 grep
不支持 PCRE。所以我的问题是,为什么在 BSD 版本的 grep
上使用 ERE,并使用非贪婪量词可以产生正确的输出,而在 GNU 版本的 grep
上却不行?这是一个bug,还是BSD版本的egrep
未记录的特性,还是我对输出的误解?
hel[^o]*o
。 - Gumbo