正则表达式中的重叠匹配

Posted

技术标签:

【中文标题】正则表达式中的重叠匹配【英文标题】:Overlapping matches in Regex 【发布时间】:2010-09-24 03:24:53 【问题描述】:

我似乎找不到这个问题的答案,我想知道是否存在。简化示例:

考虑一个字符串“nnnn”,我想在其中找到“nn”的所有匹配项——但也包括那些相互重叠的匹配项。因此正则表达式将提供以下 3 个匹配项:

    nnnn nnnn nnnn

我意识到这并不完全是正则表达式的含义,但是手动遍历字符串并对其进行解析似乎需要大量代码,考虑到实际上必须使用模式而不是文字字符串来完成匹配.

【问题讨论】:

感谢您添加此问题。我什至不知道如何以其他人可以理解的方式陈述这个问题! 【参考方案1】:

2016 年更新:

要得到nn,nn,nn,SDJMcHattie求婚the comments(?=(nn)) (see regex101)。

(?=(nn))

原始答案(2008 年)

一个可能的解决方案是使用positive look behind:

(?<=n)n

它会给你的结束位置:

    nnnn nnnn nnnn

正如Timothy Khouri 所提到的,正向前瞻更直观 (see example)

我更喜欢他的提议(?=nn)n 更简单的形式:

(n)(?=(n))

这将引用您想要的字符串的第一个位置并将捕获 group(2) 中的第二个 n

之所以如此,是因为:

任何有效的正则表达式都可以在前瞻中使用。 如果它包含捕获括号,则将保存反向引用

所以 group(1) 和 group(2) 将捕获任何 'n' 表示的内容(即使它是一个复杂的正则表达式)。


【讨论】:

另外,您也可以积极向前看:(?=nn)n ... 表示“前面有两个 N,匹配一个 N”。 对不起,我仍然没有看到请求的三个重叠捕获。您捕获了两个 n,但不是三个组。如果我将 (\d\d)(?=(\d\d)) 与 foo4237bar 匹配,我会得到两个捕获,而不是三个:42 和 37(在 Regex Coach 和 PCRE Workbench 中)。我可能很厚,所以我需要更多解释。 请再读一遍答案:(\d)(?=(\d)),而不是(\d\d)(?=(\d\d)):你会有3套捕获组数:(4)(2), (2)(3), (3)(7) 为什么不只是(?=(nn))?然后你会为每场比赛获得一个捕获组 我可能遗漏了一些东西,但@SDJMcHattie 评论看起来像 the 答案:它适用于任意表达式,而不仅仅是 ns 序列跨度> 【参考方案2】:

对捕获组使用前瞻是可行的,但代价是使您的正则表达式变得更慢和更复杂。另一种解决方案是告诉 Regex.Match() 方法下一次匹配尝试应该从哪里开始。试试这个:

Regex regexObj = new Regex("nn");
Match matchObj = regexObj.Match(subjectString);
while (matchObj.Success) 
    matchObj = regexObj.Match(subjectString, matchObj.Index + 1); 

【讨论】:

Regular-Expressions.info webmaster... => 必填 + 1。当然,你是对的。【参考方案3】:

AFAIK,没有纯粹的正则表达式方法可以立即执行此操作(即返回您请求的三个捕获而无需循环)。

现在,您可以找到一个模式一次,然后从偏移量(找到的位置 + 1)开始循环搜索。应该将正则表达式的使用与简单的代码结合起来。

[编辑] 太好了,当我基本上说出 Jan 所展示的内容时,我被否决了... [编辑 2] 要明确:简的答案更好。不是更精确,但肯定更详细,值得选择。我只是不明白为什么我的投票被否决了,因为我仍然没有看到任何不正确的地方。没什么大不了的,就是烦人。

【讨论】:

比我早1秒,我会撤回我的相同答案! @Timothy:那不会进行捕获,而且您仍然需要循环查看结果,所以我不确定优势...... @PhiLho:同样,不是真的:您可以在零宽度断言中捕获组,例如正向预测。查看我的 - 已完成 - 答案。 @PhiLho:我回复了你的评论。而且,在我看来,您的回答不如 Jan 的准确:“模式”可以指“n”,而正确的策略是指使用“nn”,然后从 offset+1 重新开始。您可能一直是这个意思,只是没有解释。 @VonC:问题很准确,模式一直是“nn”,我看不出有歧义。

以上是关于正则表达式中的重叠匹配的主要内容,如果未能解决你的问题,请参考以下文章

Vim 多行正则表达式给出重叠匹配

如何使用正则表达式查找重叠匹配?

在 C# 中获取重叠的正则表达式匹配

是否有可能有重叠的正则表达式匹配?

如何检测两个正则表达式在它们可以匹配的字符串中是不是重叠?

如何使用正则表达式找到最短的重叠匹配?