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。
使用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。