非贪婪的前瞻正则表达式

4

我需要在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

一切都很好,但最后一个部分(lookahead)是贪婪的。我需要一个非贪婪的lookahead正则表达式,但我找不到它。
我们可以使用*? +?{m,n}?应用非贪婪行为,但我无法找到这样的语法来使用(?=...)。
当我使用这个正则表达式搜索匹配项时,它只找到一个匹配项,而实际上有两个。这是因为lookahead运算符的贪婪性质。如何使用非贪婪的lookahead呢?

1
你需要 \.W\n([\d\D]*?) 吗? - Julien Spronck
1
然后移除前瞻。它们不能贪婪或懒惰。它们限制了匹配。如果你的前瞻只包含可选子模式,那么它是无用的。 - Wiktor Stribiżew
1
@Fartab ... 它应该匹配,你的 .W 部分与其他部分没有区别,它应该同样工作。 - Julien Spronck
1
@Fartab 另外,我在 regex101 上测试了下面的正则表达式(见我的答案),似乎可以匹配一切正确。 - Julien Spronck
哦,我忘了,@WiktorStribiżew 也谢谢你。 - Fartab
显示剩余8条评论
1个回答

3

我不明白为什么向前查找的贪婪性很重要,我预计以下内容可以工作:

\.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部分后面漏了问号,并且最后一个匹配需要加上美元符号。感谢@Julien。 - Fartab
2
它匹配的内容很重要!你如何告诉它匹配第一个而不是最后一个? - Matt Arnold
@MattArnold 前瞻不会消耗任何字符;它只是断言在当前扫描位置,您可以匹配一些正则表达式,但无论如何它实际上都不会推进扫描位置来匹配/消耗字符。例如,如果我想确保字符串s至少包含一个小写ASCII字符,则可以使用m = re.match(r'(?=.*[a-z])', s)m = re.match('(?=.*?[a-z])', s),每个正则表达式将为给定的输入返回相同的m值,如果m不是None,则m.group(0)仍将是空字符串。 - Booboo
@Booboo 但是在使用 REGEX 进行查找和替换时,匹配到的小写字符实例确实很重要。 - Matt Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接