Python 如何在正则表达式中使用布尔或

Python 如何在正则表达式中使用布尔或,python,regex,parsing,boolean-logic,Python,Regex,Parsing,Boolean Logic,我想使用正则表达式来查找一个子字符串,后跟可变数量的字符,后跟几个子字符串中的任意一个 芬德尔先生 "ATGTCAGGTAAGCTTAGGGCTTTAGGATT" 你应该给我: ['ATGTCAGGTAA', 'ATGTCAGGTAAGCTTAG', 'ATGTCAGGTAAGCTTAGGGCTTTAG'] 我尝试了以下所有方法,但均未成功: import re string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT" re.findall('(ATG.*TAA)|

我想使用正则表达式来查找一个子字符串,后跟可变数量的字符,后跟几个子字符串中的任意一个

芬德尔先生

"ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
你应该给我:

['ATGTCAGGTAA', 'ATGTCAGGTAAGCTTAG', 'ATGTCAGGTAAGCTTAGGGCTTTAG']
我尝试了以下所有方法,但均未成功:

import re
string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
re.findall('(ATG.*TAA)|(ATG.*TAG)', string2)
re.findall('ATG.*(TAA|TAG)', string2)
re.findall('ATG.*((TAA)|(TAG))', string2)
re.findall('ATG.*(TAA)|(TAG)', string2)
re.findall('ATG.*(TAA)|ATG.*(TAG)', string2)
re.findall('(ATG.*)(TAA)|(ATG.*)(TAG)', string2)
re.findall('(ATG.*)TAA|(ATG.*)TAG', string2)

我在这里遗漏了什么?

这不是很容易,因为a)你想要重叠匹配,b)你想要贪婪和非贪婪,以及两者之间的一切

只要字符串相当短,就可以检查每个子字符串:

import re
s = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
p = re.compile(r'ATG.*TA[GA]$')

for start in range(len(s)-6):  # string is at least 6 letters long
    for end in range(start+6, len(s)):
        if p.match(s, pos=start, endpos=end):
            print(s[start:end])
这张照片是:

ATGTCAGGTAA
ATGTCAGGTAAGCTTAG
ATGTCAGGTAAGCTTAGGGCTTTAG

因为你似乎在处理DNA序列或类似的东西,所以也一定要检查一下。

我喜欢公认的答案很好:-)也就是说,我添加这个是为了获取信息,而不是寻找分数

如果您对此有很大的需求,那么尝试在
O(N^2)
索引对上进行匹配可能很快就会变得极其缓慢。一个改进是使用
.search()
方法直接“跳跃”到可能有回报的唯一起始索引。下面就是这样

它还使用
.fullmatch()
方法,这样您就不必人为地更改“自然”regexp(例如,在您的示例中,不需要向regexp添加尾随的
$
——事实上,在下面的代码中,这样做将不再像预期的那样工作)。请注意,
.fullmatch()
是在Python3.4中添加的,因此此代码也需要Python3

最后,本文旨在概括
re
模块的
finditer()
函数/方法。虽然您不需要匹配对象(您只需要字符串),但它们更普遍适用,而且返回生成器通常比返回列表更友好

因此,不,这并不能完全满足您的需求,但在Python 3中,它可以更快地满足您的需求:

def finditer_overlap(regexp, string):
    start = 0
    n = len(string)
    while start <= n:
        # don't know whether regexp will find shortest or
        # longest match, but _will_ find leftmost match
        m = regexp.search(string, start)
        if m is None:
            return
        start = m.start()
        for finish in range(start, n+1):
            m = regexp.fullmatch(string, start, finish)
            if m is not None:
                yield m
        start += 1

打印示例中所需的内容。您尝试编写regexp的其他方法也应该有效。在本例中,速度更快,因为外循环的第二次
start
为1,并且
regexp.search(string,1)
无法找到另一个匹配项,因此生成器立即退出(因此跳过检查
O(N^2)
其他索引对)。

findall:返回字符串中所有非重叠匹配项的列表。作为旁注,
ATG.*(TAA | TAG)
将只匹配最长的字符串。这是因为
*
操作符是贪婪的。有趣的方法。时间复杂度是O(N^3)对吗?它应该是O(N^2),除非我遗漏了什么。提取所有子字符串是O(N^3)独立的(O(N^2)个子字符串,每个子字符串中复制O(N)个字符)。如果有人真的需要使用它,最好重新调用它:编译regexp,并使用它的
.match()
方法。它接受
pos
endpos
切片索引,这样就不必创建任何子字符串对象(当然,编译regexp的费用只需支付一次)。@TimPeters我想我在哪里读到过编译regex没有多大帮助,因为解释器通常都在编译它?但我相信你的话。我根据您的建议修改了答案。CPython维护了最近使用的regexp字符串到其编译的regexp对象的缓存映射,但这不是真正的点-真正的点是
re.match()
不接受切片索引,只有
regexp\u object.match()
接受切片索引。使用切片索引完全避免了创建O(N^2)子字符串对象的开销。
import re
string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
pat = re.compile("ATG.*(TAA|TAG)")
for match in finditer_overlap(pat, string2):
    print(match.group())