GNU grep、反向引用和通配符

GNU grep, backreferences and wildcards

使用grep (GNU grep 3.3) 搜索所有包含三个连续双字母的单词(结果为“bookkeeper”):

grep -E "((.)){3}" /usr/share/dict/american-english

将此更改为搜索包含三个双字母的单词,每个字母后跟字母“i”(结果为“Mississippi”):

grep -E "((.)i){3}" /usr/share/dict/american-english

将此更改为搜索包含三个双字母的单词,每个字母后跟任意一个字母(有几个结果):

grep -E "((.).){3}" /usr/share/dict/american-english

将此更改为搜索三个双字母之间由一个可选的单个字母分隔的单词(甚至更多结果):

grep -E "((.).?){3}" /usr/share/dict/american-english

现在,我的原始任务终于完成了:搜索包含三个双字母的所有单词:

grep -E "((.).*){3}" /usr/share/dict/american-english

但这会导致一个空集。为什么? .? 如何匹配 .* 不匹配的内容?

POSIX 正则表达式引擎不能很好地处理 back-references 的模式,matching back references is an NP complete problem 可能会提供一些关于为什么如此困难的提示。

由于您使用的是 GNU grep,问题很容易通过 PCRE 引擎解决,

grep -P '((.).*){3}' file

因为 PCRE 引擎可以比 POSIX 正则表达式引擎更有效地处理 back-references。

参见online demo