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


78
>>> match = re.findall(r'\w\w', 'hello')
>>> print match
['he', 'll']

由于\ w \ w表示两个字符,因此应使用'he'和'll'。但是,为什么“ el”和“ lo”与正则表达式匹配?

>>> match1 = re.findall(r'el', 'hello')
>>> print match1
['el']
>>>

Answers:


110

findall默认情况下不会产生重叠匹配。但是,此表达式可以:

>>> re.findall(r'(?=(\w\w))', 'hello')
['he', 'el', 'll', 'lo']

(?=...)是一个前瞻性断言

(?=...)如果...下一个匹配,则匹配,但不使用任何字符串。这称为先行断言。例如, 仅在后跟Isaac (?=Asimov)时匹配。'Isaac ''Asimov'


但是我不明白,如果它在正向超前断言中,为什么会前进到下一个字母。你能解释一下吗?
MrZH6'4


11

除零长度断言外,输入中的字符将始终在匹配中使用。如果您想一次捕获一次输入字符串中的某些字符,则需要在正则表达式中使用零长度断言。

有几种零长度断言(例如^(输入/行的开始),$(输入/行的结束),\b(单词边界)),但是环顾四周((?<=)正向后看和(?=)正向前看)是唯一的方法您可以捕获输入中的重叠文本。负向环视((?<!)负向后视,(?!)负向前视)在这里不是很有用:如果它们断言为true,则内部捕获会失败;如果它们断言为假,则匹配失败。这些断言是零长度的(如前所述),这意味着它们将断言而不会消耗输入字符串中的字符。如果断言通过,它们实际上将匹配空字符串。

应用以上知识,适合您的情况的正则表达式将是:

(?=(\w\w))

0

我不是正则表达式专家,但我想回答我的类似问题 问题

如果要与前瞻性一起使用捕获组:

正则表达式示例:(\ d)(?=。\ 1)

字符串:5252

这将匹配前5个和前2个

(\ d)是一个捕获组,(?= \ d \ 1)是要匹配捕获组1后面的任何数字,而不消耗字符串,因此允许重叠

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.