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

How to use Boolean OR inside a regex

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

个 re.findall
"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 序列或类似的东西,请确保也检查一下 Biopython

我非常喜欢接受的答案:-)也就是说,我添加这个是为了提供信息,而不是为了加分。

如果您对此非常需要,尝试对 O(N^2) 对索引进行匹配可能很快就会变得慢得无法忍受。一项改进是使用 .search() 方法直接 "leap" 到唯一可能获得回报的起始指数。所以下面这样做了。

它还使用 .fullmatch() 方法,这样您就不必人为更改 "natural" 正则表达式(例如,在您的示例中,无需添加尾随 $到正则表达式 - 事实上,在下面的代码中这样做将不再按预期工作)。注意 .fullmatch() 是在 Python 3.4 中加入的,所以这段代码也需要 Python 3!

最后,这打算泛化re模块的finditer()function/method。虽然您不需要匹配对象(您只需要字符串),但它们的适用性要普遍得多,并且返回生成器通常也比返回列表更友好。

所以,不,这并不能完全满足您的需求,但可以得到您想要的东西,在 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

然后,例如,

import re
string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
pat = re.compile("ATG.*(TAA|TAG)")
for match in finditer_overlap(pat, string2):
    print(match.group())

打印您在示例中想要的内容。您尝试编写正则表达式的其他方法也应该有效。在这个例子中它更快,因为第二次围绕外循环 start 是 1,并且 regexp.search(string, 1) 找不到另一个匹配项,所以生成器立即退出(所以跳过检查 O(N^2) 其他索引对)。