【发布时间】:2017-04-23 15:19:46
【问题描述】:
试图获取连续重复字母出现两次或三次的单词。无法找到使用 ERE 使用量词和捕获组的方法
$ grep --version | head -n1
grep (GNU grep) 2.25
$ # consecutive repeated letters occurring twice
$ grep -m5 -xiE '[a-z]*([a-z])\1[a-z]*[a-z]*([a-z])\2[a-z]*' /usr/share/dict/words
Abbott
Annabelle
Annette
Appaloosa
Appleseed
$ # no output for this, why?
$ grep -m5 -xiE '([a-z]*([a-z])\2[a-z]*){2}' /usr/share/dict/words
虽然适用于-P
$ grep -m5 -xiP '([a-z]*([a-z])\2[a-z]*){2}' /usr/share/dict/words
Abbott
Annabelle
Annette
Appaloosa
Appleseed
$ grep -m5 -xiP '([a-z]*([a-z])\2[a-z]*){3}' /usr/share/dict/words
Chattahoochee
McConnell
Mississippi
Mississippian
Mississippians
感谢 Casimir et Hippolyte 提供更简单的输入和正则表达式来测试此行为
$ echo 'aazbb' | grep -E '(([a-z])\2[a-z]*){2}' || echo 'No match'
aazbb
$ echo 'aazbbycc' | grep -E '(([a-z])\2[a-z]*){2}([a-z])\3[a-z]*' || echo 'No match'
aazbbycc
$ echo 'aazbbycc' | grep -P '(([a-z])\2[a-z]*){3}' || echo 'No match'
aazbbycc
$ # failing case
$ echo 'aazbbycc' | grep -E '(([a-z])\2[a-z]*){3}' || echo 'No match'
No match
sed 的行为也相同
$ sed --version | head -n1
sed (GNU sed) 4.2.2
$ echo 'aazbb' | sed -E '/(([a-z])\2[a-z]*){2}/! s/.*/No match/'
aazbb
$ echo 'aazbbycc' | sed -E '/(([a-z])\2[a-z]*){2}([a-z])\3[a-z]*/! s/.*/No match/'
aazbbycc
$ # failing case
$ echo 'aazbbycc' | sed -E '/(([a-z])\2[a-z]*){3}/! s/.*/No match/'
No match
相关搜索链接,我查了一些,但没有得到任何接近这个问题的东西
如果这在grep 或sed 的较新版本中得到解决,请告诉我。此外,如果问题出现在非 GNU 实现中
【问题讨论】:
-
还要注意:
echo 'aazbb' | grep -m5 -xiE '(([a-z])\2[a-z]*){2}有效,echo 'aazbbycc' | grep -m5 -xiE '(([a-z])\2[a-z]*){3}无效。我怀疑 grep 会默默地中止复杂度过高的模式。 -
@CasimiretHippolyte 似乎是这样,感谢您的输入。我今天将尝试在这些行上进行更多搜索:)
-
关于您在 Ed Morton 回答中的评论,BRE 和 ERE 模式下的 grep 以完全不同的方式工作(与使用 -P 的方式不同),它不使用回溯机制(简而言之,所有可能的路径都被存储和最长的胜利)。
-
请注意,gnu 3 文档说反向引用存在问题,并且可能由于堆栈溢出而悄然死亡。递归限制也可能是 2。
-
@Sundeep - 是的,我想就是这样。但是,关于人为限制。很多时间作者会将这个限制设置为默认值,而不是等待那个指数时间来找出答案。您的第 2 组构造很简单,但是它们通常不会区分,它可能很复杂。我认为问题在于嵌套组构造中的反向引用。您可以配置全局 grep 环境参数来更改这些参数,即。堆栈大小,递归限制等。但是我不确定。