非贪婪的前瞻正则表达式

Posted

技术标签:

【中文标题】非贪婪的前瞻正则表达式【英文标题】:Non-greedy lookahead regex 【发布时间】:2016-06-08 09:11:06 【问题描述】:

我有一个文件需要从 Python 中提取一些数据。其结构如下:

.I 1
.T
some multiline text
.A
some multiline text
.B
some multiline text
.W
some multiline text
.I 2
.T
some multiline text
.A
some multiline text
.B
some multiline text
.W
some multiline text

如您所见,有一些重复的重复模式。我需要一一提取它们。这是我的脑电图:

\.I\s(\d*)\n       # .I section
\.T\n([\d\D]*?)    # .T section
\.A\n([\d\D]*?)    # .A section
\.B\n([\d\D]*?)    # .B section
\.W\n([\d\D]*)     # .W section
(?=\.I\s+\d+)     # look ahead section, which behaves greedy

一切都很好,但是最后一部分(前瞻)是贪婪的。我需要一个,但我找不到它。

我们可以使用 *? +? m,n? 应用非贪婪行为,但我找不到 (?=...) 的这种语法

当我使用此正则表达式搜索匹配项时,它只找到一个匹配项,而有两个匹配项。这是因为前瞻运算符的贪婪本性。我怎样才能有一个非贪婪的前瞻?

【问题讨论】:

当我将您的正则表达式粘贴到 regex101.com 时,它告诉我最后一个问号有错误。你也看到了吗? 另外,你不想要\.W\n([\d\D]*?) 吗? 然后移除前瞻。他们不能贪婪或懒惰。他们限制了比赛。如果您的前瞻仅包含可选的子模式,则没有用。 @Fartab ...它应该匹配,您的 .W 部分与其他部分没有什么不同,它应该工作相同 @Fartab 也是,我在 regex101 中测试了下面的雷鬼(见我的答案),似乎一切都很好。 【参考方案1】:

我不明白为什么贪婪地向前看很重要,我希望以下方法起作用:

\.I\s(\d*)\n
\.T\n([\d\D]*?)
\.A\n([\d\D]*?)
\.B\n([\d\D]*?)
\.W\n([\d\D]*?)
(?=\.I\s+\d+|$)

现在我想起来了,我认为 Wiktor Stribiżew 是对的。向前看不能是贪婪或懒惰的:匹配或不匹配,匹配什么并不重要。

【讨论】:

我的错误是在 .W 部分之后缺少问号,最后一场比赛还需要一个 $。谢谢@朱利安 匹配的内容很重要!你如何告诉它匹配第一个匹配而不是最后一个?

以上是关于非贪婪的前瞻正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

负前瞻正则表达式贪婪(为啥.*?太贪婪)

js正则匹配总结

正则表达式第三回--模式分组与前瞻

正则表达式贪婪与非贪婪模式

python正则表达式贪婪与非贪婪模式

python正则表达式贪婪算法与非贪婪算法与正则表达式子模式的简单应用