提问人:futurenext110 提问时间:7/11/2012 最后编辑:KL-7futurenext110 更新时间:6/2/2021 访问量:48488
如何找到与正则表达式重叠的匹配项?
How to find overlapping matches with a regexp?
问:
>>> 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']
>>>
答:
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)
评论