【问题标题】: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']
>>>

【问题讨论】:

标签: python regex overlapping


【解决方案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后面的任何数字而不消耗字符串,因此允许重叠

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多