我需要知道下一个正则表达式的匹配的开始和结束索引:
pat = re.compile("(?=(ATG(?:(?!TAA|TGA|TAG)\w\w\w)*))")
Run Code Online (Sandbox Code Playgroud)
示例字符串是 s='GATGDTATGDTAAAA'
pat.findall(s)返回所需的匹配['ATGDTATGD', 'ATGDTAAAA'].如何提取开始和结束索引?我试过了:
iters = pat.finditer(s)
for it in iters:
print it.start()
print it.end()
Run Code Online (Sandbox Code Playgroud)
然而,it.end()总是与之一致it.start(),因为我的模式的开始从那开始(?=所以它不消耗任何字符串(我需要它来捕获重叠的匹配).显然pat.findall提取了所需的字符串,但如何获取启动和停止索引?
正如@Tomalak所说,正则表达式引擎没有重叠匹配的内置概念,因此没有找到"聪明"的解决方案(结果证明是错误的 - 见下文).但是用循环来做这件事很简单:
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
Run Code Online (Sandbox Code Playgroud)
哪个显示
match at 1:10 'ATGDTATGD'
match at 6:15 'ATGDTAAAA'
Run Code Online (Sandbox Code Playgroud)
它的工作原理是在最后一场比赛开始之后重新开始搜索一个角色,直到找不到更多的匹配.
如果您想生活危险,可以对原始finditer代码进行2个字符的更改:
print it.start(1)
print it.end(1)
Run Code Online (Sandbox Code Playgroud)
也就是说,获取first(1)捕获组的开始和结束.通过不传递参数,你得到整个匹配的开始和结束 - 但是当然匹配的断言总是匹配一个空字符串(所以start和end是相等的).
我说这是危险的,因为生活的捕获组的语义内的断言(无论是前瞻还是回顾后,积极或消极,...)是模糊的最好的.很难说你是否在这里偶然发现了一个错误(或实施意外)!可爱:-)
编辑:经过一夜的睡眠和关于Python-Dev的简短讨论,我相信这种行为是有意的(也是如此可靠).要查找正则表达式R的所有(可能重叠!)匹配,请将其包装如下:
pat = re.compile("(?=(" + R + "))")
Run Code Online (Sandbox Code Playgroud)
然后
for m in pat.finditer(some_string):
m.group(1) # the matched substring
m.span(1) # the slice indices of the match substring
# etc
Run Code Online (Sandbox Code Playgroud)
工作良好.
最好读(?=(R))作"在这里匹配一个空字符串,但只有R从这里开始,如果成功,则将有关R匹配的信息放入组1".然后finditer()在匹配空字符串时继续进行:它将搜索的开始移动到下一个字符,然后再次尝试(与我的第一个答案中的手动循环相同).
使用它findall()是比较棘手的,因为如果R包含捕获组,你将获得所有这些(不能选择,因为你可以使用匹配对象,如finditer()返回).
| 归档时间: |
|
| 查看次数: |
179 次 |
| 最近记录: |