Python正则表达式找到所有重叠的匹配项?


98

我正在尝试在Python 2.6中使用re查找更大系列的数字中的每10位数字系列。

我很容易就能抓住不重叠的比赛,但我希望数字系列中的每场比赛。例如。

在“ 123456789123456789”中

我应该得到以下列表:

[1234567891,2345678912,3456789123,4567891234,5678912345,6789123456,7891234567,8912345678,9123456789]

我已经找到了对“超前”的引用,但是我所看到的示例仅显示了成对的数字,而不是更大的分组,而且我无法将其转换为两位数以外的数字。


6
当重叠匹配在同一点开始时,提出的解决方案将不起作用,例如,将“ a | ab | abc”与“ abcd”匹配只会返回一个结果。有没有一个解决方案,该解决方案不涉及多次调用match()并手动跟踪“结束”边界?
维罗·德·阿劳霍

@VítorDeAraújo:重叠的正则表达式(a|ab|abc)通常可以重写为带有嵌套捕获组的非重叠正则表达式,例如(a(b(c)?)?)?,在解包匹配项时,我们忽略除最外层(即最左边)捕获组之外的所有正则表达式;诚然,这有点痛苦,而且不太清晰。这也是匹配性能更高的正则表达式。
smci

Answers:


175

在前瞻范围内使用捕获组。前瞻捕捉您感兴趣的文本,但是实际匹配在技术上是前瞻之前的零宽度子字符串,因此匹配在技术上是不重叠的:

import re 
s = "123456789123456789"
matches = re.finditer(r'(?=(\d{10}))',s)
results = [int(match.group(1)) for match in matches]
# results: 
# [1234567891,
#  2345678912,
#  3456789123,
#  4567891234,
#  5678912345,
#  6789123456,
#  7891234567,
#  8912345678,
#  9123456789]

2
我的答案至少比这个答案快2倍。但是,我赞成这种解决方案是棘手的。
eyquem

16
说明=而不是搜索模式(10位数字),而是搜索该模式之后的所有内容。因此,它将找到字符串的位置0,字符串的位置1,依此类推。然后,它获取group(1)-匹配的模式并列出这些列表。很酷。
Tal Weiss

我不知道您可以在前行中使用匹配组,通常不应该将它们包含在匹配项中(匹配的子组确实不会出现完全匹配项)。由于该技术似乎仍在Python 3.4中有效,因此我认为它被认为是一项功能,而不是错误。
JAB

10
我加入了StackOverflow,回答了问题,并提高了我的声誉,所以我可以投票赞成这个答案。我现在停留在Python 2.4上,所以我不能使用Python 3的更高级的regex函数,这只是我一直在寻找的怪异技巧。
TheSoundDefense 2014年

2
您能否在代码中添加更多说明。按照堆栈溢出的方法,将代码包含在答案中并不是最好的方法。它肯定会帮助人们。
阿克斯哈扎里

77

您也可以尝试使用支持重叠匹配的第三方regex模块(不是re)。

>>> import regex as re
>>> s = "123456789123456789"
>>> matches = re.findall(r'\d{10}', s, overlapped=True)
>>> for match in matches: print match
...
1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

17

我喜欢正则表达式,但是这里不需要它们。

只是

s =  "123456789123456789"

n = 10
li = [ s[i:i+n] for i in xrange(len(s)-n+1) ]
print '\n'.join(li)

结果

1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

10
仅在这里不需要正则表达式,因为您正在“在一系列较大的数字中”应用特殊知识,因此您已经知道每个位置0 <= i < len(s)-n+1都将保证是10位数字匹配的开始。另外,我认为您的代码可能会加快速度,对于代码高尔夫球而言,这对于提高速度很有趣。
smci
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.