如何使用正则表达式查找重叠匹配?
Posted
技术标签:
【中文标题】如何使用正则表达式查找重叠匹配?【英文标题】:How to find overlapping matches with a regexp? 【发布时间】:2012-07-10 23:10:09 【问题描述】:>>> 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']
>>>
【问题讨论】:
Lookahead 【参考方案1】:findall
默认情况下不会产生重叠匹配。然而,这个表达式确实:
>>> re.findall(r'(?=(\w\w))', 'hello')
['he', 'el', 'll', 'lo']
这里(?=...)
是lookahead assertion:
(?=...)
匹配如果...
匹配下一个,但不消耗任何 细绳。这称为前瞻断言。例如,Isaac (?=Asimov)
将匹配'Isaac '
,前提是它后面跟着'Asimov'
。
【讨论】:
但我不明白如果它在积极的前瞻断言中,为什么它会前进到下一个字母。请解释一下好吗? @MrZH6 我猜这是由于组捕获(\w\w 周围的大括号)。实际匹配仍然是一个空字符串,而第 1 组用 \w\w 填充(您可以在regex101.com 进行测试)。所以我相信它会在一个组中捕获它,但不会超过它,因为匹配是零长度的。而python的re.findall将打印捕获的组docs.python.org/3/library/re.html#re.findall【参考方案2】:您可以使用new Python regex module,它支持重叠匹配。
>>> import regex as re
>>> match = re.findall(r'\w\w', 'hello', overlapped=True)
>>> print match
['he', 'el', 'll', 'lo']
【讨论】:
【参考方案3】:除了零长度断言外,输入中的字符将始终在匹配中被消耗。如果您想在输入字符串中多次捕获某些字符,则需要在正则表达式中进行零长度断言。
有几个零长度断言(例如^
(输入/行的开头)、$
(输入/行的结尾)、\b
(字边界)),但环顾四周(@987654324 @positive look-behind 和 (?=)
positive look-ahead)是您可以从输入中捕获重叠文本的唯一方法。否定环视((?<!)
negative look-behind,(?!)
negative look-ahead)在这里不是很有用:如果它们断言为真,则内部捕获失败;如果他们断言为假,则匹配失败。这些断言是零长度的(如前所述),这意味着它们将断言而不消耗输入字符串中的字符。如果断言通过,它们实际上将匹配空字符串。
应用上述知识,适用于您的情况的正则表达式将是:
(?=(\w\w))
【讨论】:
【参考方案4】:我不是正则表达式专家,但我想回答我类似的question。
如果您想使用具有前瞻功能的捕获组:
示例正则表达式:(\d)(?=.\1)
字符串:5252
这将匹配前 5 个以及前 2 个
(\d)
是做一个捕获组,(?=\d\1)
是匹配捕获组1后面的任何数字而不消耗字符串,因此允许重叠
【讨论】:
以上是关于如何使用正则表达式查找重叠匹配?的主要内容,如果未能解决你的问题,请参考以下文章