Python 获取重叠匹配的开始和停止索引?

Python 获取重叠匹配的开始和停止索引?,python,regex,Python,Regex,我需要知道下一个正则表达式中匹配项的开始索引和结束索引: pat = re.compile("(?=(ATG(?:(?!TAA|TGA|TAG)\w\w\w)*))") 示例字符串是s='GATGDTATGDTAAAA' pat.findall返回所需的匹配项['ATGDTATGD','ATGDTAAAA']。如何提取开始索引和结束索引? 我试过: 但是,it.end()总是与it.start()一致,因为我的模式的开头是从开始的(?=,所以它不消耗任何字符串(我需要它来捕获重叠的匹配)显然,

我需要知道下一个正则表达式中匹配项的开始索引和结束索引:

pat = re.compile("(?=(ATG(?:(?!TAA|TGA|TAG)\w\w\w)*))")
示例字符串是
s='GATGDTATGDTAAAA'

pat.findall
返回所需的匹配项
['ATGDTATGD','ATGDTAAAA']
。如何提取开始索引和结束索引? 我试过:


但是,
it.end()
总是与
it.start()
一致,因为我的模式的开头是从
开始的(?=
,所以它不消耗任何字符串(我需要它来捕获重叠的匹配)显然,
pat.findall
提取了所需的字符串,但如何获取开始和停止索引?

正则表达式中没有重叠匹配

要么匹配,要么不匹配。匹配的任何内容只能是一个匹配/子匹配的一部分


看,ahead是短暂的,它们不会增加任何实际计数器。

正如@Tomalak所说,regexp引擎没有内置的重叠匹配概念,因此找不到“聪明”的解决方案(,结果是错误的-见下文)。但使用循环实现它很简单:

import re
pat = re.compile("ATG(?:(?!TAA|TGA|TAG)\w\w\w)*")
s = 'GATGDTATGDTAAAA'
i = 0
while True:
    m = pat.search(s, i)
    if m:
        start, end = m.span()
        print "match at {}:{} {!r}".format(start, end, m.group())
        i = start + 1
    else:
        break
哪个显示

match at 1:10 'ATGDTATGD'
match at 6:15 'ATGDTAAAA'
它的工作原理是在最后一个匹配开始后的一个字符上重新开始搜索,直到再也找不到匹配为止

“聪明”还是定时炸弹? 如果你想过上危险的生活,你可以对原来的
finditer
code:

print it.start(1)
print it.end(1)
也就是说,获取第一个(
1
)捕获组的开始和结束。通过不传递参数,您可以获得匹配的开始和结束作为一个整体—当然,匹配断言总是匹配空字符串(因此开始和结束是相等的)

我说这是危险的,因为断言中捕获组的语义(无论是向前看还是向后看,正面还是负面,…)充其量都是模糊的。很难说您是否在这里遇到了错误(或实现事故)!可爱:-)

编辑:经过一夜的睡眠和对pythondev的简短讨论,我相信这种行为是有意的(也是如此可靠)。要查找regexp R的所有匹配项(可能重叠!),请将其按如下方式包装:

pat = re.compile("(?=(" + R + "))")
然后

for m in pat.finditer(some_string):
    m.group(1)  # the matched substring
    m.span(1)   # the slice indices of the match substring
    # etc
很好

最好将
(?=(R))
解读为“在此处匹配一个空字符串,但前提是
R
从此处开始,如果成功,请将匹配内容的信息放入第1组”。然后,
finditer()
继续匹配空字符串时的操作:它将搜索的开始移动到下一个字符,然后重试(与我第一个答案中的手动循环相同)


将其与
findall()
一起使用更为棘手,因为如果
R
也包含捕获组,您将获得所有捕获组(无法拾取和选择,就像您可以使用匹配对象(如
finditer()
返回)一样)。

您的
开始()
结束()
finditer()中的索引
返回相同的数字,因为正则表达式中没有重叠的匹配项。但你可能会相信其他的东西。如果你编辑你的答案,我可以撤销否决票,否则否决票会被锁定。不,我不会。也许下次你在投下反对票之前会花更多的时间。对不起,我误解了你的问题,一开始我不清楚你所说的重叠比赛是什么意思。但是,有时人们在认真尝试帮助时会犯错误,因此,我认为你的态度是不必要的。礼貌地解释某人可能误解了你并不难。大多数人在被礼貌地告知后,会表示歉意,并寻求做正确的事情,有时甚至会比一开始没有误解时付出更大的努力,以弥补他们的错误。如果你粗鲁无礼,你将失去一切考虑。如果我粗鲁无礼,请原谅。感谢您的帮助。我看到您已经删除了其他评论,也许是我误判了您,我很抱歉在发布之前没有花更多时间理解您的问题。@Tim Peters有趣的建议,更改了两个字符。我想了想,并尝试添加0,因为我认为我正在匹配整个匹配!所以在这种情况下,整个组是空的,但子组不是:-)@msh,完全正确!这正是为什么我不愿意依赖它的原因:在一个空的火柴里面有一个非空的火柴的概念只是有点尖叫“bug alert!”;-)@蒂姆看起来我在理论上是对的,但在实践中却是错的。NET正则表达式也做同样的事情-您可以在断言中提取组的长度,即使匹配的总长度为0。@Tomalak,我们在那里是同一条船;-)现在尝试在Python开发人员邮件列表中讨论它。
for m in pat.finditer(some_string):
    m.group(1)  # the matched substring
    m.span(1)   # the slice indices of the match substring
    # etc