如何找到与正则表达式重叠的匹配项?

How to find overlapping matches with a regexp?

提问人:futurenext110 提问时间:7/11/2012 最后编辑:KL-7futurenext110 更新时间:6/2/2021 访问量:48488

问:

>>> 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']
>>>
Python 正则表达式 重叠

评论

5赞 Pavan Manjunath 7/11/2012
展望未来

答:

145赞 Otto Allmendinger 7/11/2012 #1

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

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

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

(?=...)匹配 if matches next,但不消耗任何 字符串。这称为前瞻断言。例如,仅当它后跟 ....Isaac (?=Asimov)'Isaac ''Asimov'

评论

4赞 MrZH6 4/2/2020
但我不明白,如果它在积极的前瞻断言中,为什么它会前进到下一个字母。你能解释一下吗?
1赞 Sviatozar Petrenko 1/27/2022
@MrZH6 我想这是由于组捕获(\w\w 周围的大括号)。实际匹配仍然是一个空字符串,而组 1 填充了 \w\w(您可以在 regex101.com 处测试)。所以我相信它会在一个小组中捕捉到它,但不会超越它,因为比赛的长度为零。Python 的 re.findall 将打印捕获的组 docs.python.org/3/library/re.html#re.findall
13赞 nhahtdh 7/11/2012 #2

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

有几个零长度断言(例如 (输入/行的开头)、(输入/行的结尾)、(单词边界)),但环视(正向后视和正向前视)是从输入中捕获重叠文本的唯一方法。消极的环视(消极的后视,消极的展望)在这里不是很有用:如果它们断言为真,那么内部捕获就失败了;如果他们断言为 false,则匹配失败。这些断言的长度为零(如前所述),这意味着它们将在不消耗输入字符串中的字符的情况下进行断言。如果断言通过,它们实际上将匹配空字符串。^$\b(?<=)(?=)(?<!)(?!)

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

(?=(\w\w))
53赞 David C 9/24/2013 #3

您可以使用新的 Python 正则表达式模块,该模块支持重叠匹配。

>>> import regex as re
>>> match = re.findall(r'\w\w', 'hello', overlapped=True)
>>> print match
['he', 'el', 'll', 'lo']
0赞 Obay Abd-Algader 2/4/2019 #4

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

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

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

字符串:5252

这将匹配前 5 个以及前 2 个

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