【问题标题】:Why is my positive lookahead assertion consuming the string and not matching correctly?为什么我的积极前瞻断言会消耗字符串并且不正确匹配?
【发布时间】:2019-07-18 07:10:40
【问题描述】:

我正在尝试查找字符串中子字符串的所有出现并使用正则表达式打印它们的开始和结束索引。

例如, 字符串 = 'bbbcbb' 子='bb' 我必须得到 (0,1) (1,2) (4,5) 作为我的输出。

我的代码:

import re
matches = list(re.finditer(r'bb(?=[a-zA-Z]|$)', 'bbbcbb'))

输出:

[<_sre.SRE_Match object; span=(0, 2), match='bb'>, 
<_sre.SRE_Match object;span=(4, 6), match='bb'>]

我浏览了https://docs.python.org/3/library/re.html 上的文档,据我了解,前瞻断言将起作用

  1. 在位置 0,它将匹配 'bb' 与 "bb" 后跟 "b"。即bbbcbb
  2. 在位置 1,它将匹配 'bb' 与“bb”后跟“c”。即bbbcbb
  3. 然后它将不匹配,直到位置 4 将匹配 'bb' 与 "bb" 后跟 $ .i.e. bbbcbb

为什么前瞻断言忽略了 (1,3) 位置的 b'bb'cbb?还是我对前瞻断言的理解有缺陷?

【问题讨论】:

  • 您描述的算法可以使用(?=bb) 正则表达式完成。如果您希望它捕获bb,请使用(?=(bb))Link
  • $ 是一个特殊字符,表示字符串的结尾。

标签: python regex python-3.x


【解决方案1】:

这与您的前瞻无关,是由re 未返回重叠匹配引起的。 这是一个更简单的例子:

import re

regex = re.compile("aa")
results = list(regex.finditer("aaaa"))
#  You expect to get (0, 2), (1, 3), (2, 4)
print(results)
>>> [<_sre.SRE_Match object; span=(0, 2), match='aa'>,
     <_sre.SRE_Match object; span=(2, 4), match='aa'>]

正确的方法是使用组和前瞻,如下所述:Python regex find all overlapping matches?

【讨论】:

  • 这不会返回匹配子串的索引。我需要找到匹配子串的索引。
  • 您可以使用groups 查找被捕获的组并将其添加到比赛的开始索引中。
  • 我试过了。但是 groups 函数返回子字符串本身。我所做的是将字符串的长度 - 1 添加到匹配的开始索引。
  • 您可以添加另一个组以查找实际字符串regex = re.compile("(?=(aa))"),然后将len(x.groups(1)[0])) 添加到开始索引。这使您的代码对您要查找的内容的依赖性降低。
【解决方案2】:

模式'bb(?=[a-zA-Z]|$) 将匹配 2 个字符而不是 1 个,断言右边是字符 a-z 或字符串的结尾。

使用re.finditer,您可以更新您的模式以匹配单个b,并将单个b 放入正向前瞻中:

import re
matches = list(re.finditer(r'b(?=b)', 'bbbcbb'))
for m in matches:
    print(m.span())

结果

(0, 1)
(1, 2)
(4, 5)

【讨论】:

    猜你喜欢
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-12
    相关资源
    最近更新 更多