在大海捞针中查找字符串*和*的子字符串

时间:2012-01-21 17:10:00

标签: regex string substring

假设您有一个字符串(例如needle)。它的19个连续子串是:

needle
needl eedle
need eedl edle
nee eed edl dle
ne ee ed dl le
n e d l

如果我要建立一个正则表达式,在大海捞针中匹配我可以做的任何子串:

/(needle|needl|eedle|need|eedl|edle|nee|eed|edl|dle|ne|ee|ed|dl|le|n|e|d|l)/

但它看起来并不优雅。有没有更好的方法来创建一个贪婪地匹配给定字符串的任何一个子串的正则表达式?

此外,如果我提出另一个约束,想要仅匹配长于阈值的子串,例如对于至少3个字符的子串:

/(needle|needl|eedle|need|eedl|edle|nee|eed|edl|dle)/

注意:我故意没有提到任何特定的正则表达方言。请说明您在答案中使用的是哪一个。

4 个答案:

答案 0 :(得分:4)

正如Qtax建议的那样,表达式

n(e(e(d(l(e)?)?)?)?)?|e(e(d(l(e)?)?)?)?|e(d(l(e)?)?)?|d(l(e)?)?|l(e)?|e

如果你想编写一个明确的正则表达式(egrep语法,可选择用(...)替换(?:...)),

将是你要走的路。这比初始解决方案更好的原因是,与原始版本中的O(n ^ 3)空间相比,压缩版本仅需要O(n ^ 2)空间,其中n是输入的长度。尝试使用extraordinarily作为输入来查看差异。我想在那里使用许多正则表达式引擎时,压缩版本也更快。

表达式

nee(d(l(e)?)?)?|eed(l(e)?)?|edl(e)?|dle

将查找长度为3或更长的子串。

正如vhallac所指出的,生成的正则表达式有点冗余,可以进行优化。除了提议的Emacs工具之外,还有一个Perl包Regexp::Optimizer,我希望在这里提供帮助,但第一个正则表达式的快速检查失败。

请注意,默认情况下,许多regexp引擎执行非重叠搜索。请根据您的问题要求进行检查。

答案 1 :(得分:3)

我找到了优雅的 almostsolution ,这取决于你只需要一个正则表达式。例如,这里是regexp,它找到长度为7的公共子串(perl):

"$needle\0$heystack" =~ /(.{7}).*?\0.*\1/s

匹配字符串位于 \ 1 中。字符串不应包含用作分隔符的空字符。

你应该制作一个循环,它的长度与针的长度一致并且达到下限阈值并尝试匹配正则表达式。

答案 2 :(得分:1)

  

是否有更好的方法来创建一个匹配任何一个的正则表达式   给定字符串的子串?

没有。但是你可以轻松地生成这样的表达。

答案 3 :(得分:-2)

也许你只是在寻找 .*(.{1,6}).*