为什么re.findall在查找字符串中的三元组项时不特定?Python



所以我有四行代码

seq= 'ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA'

OR_0 = re.findall(r'ATG(?:...){9,}?(?:TAA|TAG|TGA)',seq)  

让我先解释一下我要做什么…如果这让你感到困惑,我很抱歉,但我会尽力解释清楚的。

所以我正在寻找以'ATG'开头的序列,后面跟着任何单词字符的3个单位[例如。'GGG','GTT','TTA'等]直到遇到'TAA','TAG'或'TGA'我还希望它们至少有30个字符长…因此有{9,}?

这在一定程度上起作用,但如果你注意到seq中有ATG GAA GTT GGA TGA AAG TGG AGG TAA AGA GAA GAC GTT TGA

在这种情况下,它应该找到'ATGGAAGTTGGATGA'如果它从第一个'ATG'开始一直到下一个'TAA' 'TAG'或'TGA'

然而

当您运行OR_0行代码时,它会返回整个seq字符串。我不知道如何使它只考虑第一个'TAA','TAG'或'TGA',然后是第一个'ATG'

当以3为单位读取时,如果'ATG'后面跟着另一个'ATG',那么没关系,它不应该重新开始,但如果在以3为单位读取时遇到'TAA','TAG'或'TGA',它应该停止。

我的问题,为什么re.findall找到'ATG'xxx-xxx-['TAA','TAG'或'TGA']的最长序列,而不是'TAA','TAG'或'TGA'的第一次出现在以3为单位的单词字符分隔的ATG之后?

再一次,如果这让你感到困惑,我很抱歉但它混淆了我基于这条初始文本行的多个数据集我试图找出为什么

如果你想让你的regex在第一个TAA|TAG|TGA处停止匹配,但仍然只有在至少有九个三个字母的块时才成功,以下可能会有所帮助:

>>> import re
>>> regexp = r'ATG(?:(?!TAA|TAG|TGA)...){9,}?(?:TAA|TAG|TGA)'
>>> re.findall(regexp, 'ATGAAAAAAAAAAAAAAAAAAAAAAAAAAATAG')
['ATGAAAAAAAAAAAAAAAAAAAAAAAAAAATAG']
>>> re.findall(regexp, 'ATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAG')
['ATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAG']
>>> re.findall(regexp, 'ATGAAATAGAAAAAAAAAAAAAAAAAAAAATAG')
[]

这使用负前向(?!TAA|TAG|TGA)来确保三个字符块在匹配三个字符块之前是而不是 TAA|TAG|TGA

请注意,如果落在三个字符边界上,则TAA|TAG|TGA仍然可以成功匹配:

>>> re.findall(regexp, 'ATGAAAATAGAAAAAAAAAAAAAAAAAAAATAG')
['ATGAAAATAGAAAAAAAAAAAAAAAAAAAATAG']

如果长度不是必需的,那么它很容易:

>>> import re
>>> seq= 'ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA'
>>> regex = re.compile(r'ATG(?:...)*?(?:TAA|TAG|TGA)')
>>> regex.findall(seq)
['ATGGAAGTTGGATGA']

无论如何,我相信,根据你的解释,你以前的regex实际上是在做你想要的:搜索匹配至少30个字符,从ATG开始,以TGA结束。

在您的问题中,您首先声明您需要至少30个字符的匹配,因此您放入{9,}?,但之后您希望匹配任何匹配。你不能两者兼得,选择一个。如果长度很重要,请保留您已经拥有的正则表达式,并且您得到的结果是正确的

你不需要正则表达式。

def chunks(l, n):
    """ Yield successive n-sized chunks from l.
    from: http://stackoverflow.com/a/312464/1561176
    """
    for i in xrange(0, len(l), n):
        yield l[i:i+n]
def method(sequence, start=['ATG'], stop=['TAA','TAG','TGA'], min_len=30):
    response = ''
    started = False
    for x in chunks(sequence, 3):
        if x in start:
            started = True
            response += x
        elif x in stop and started:
            if len(response) >= min_len:
                yield response + x
                response = ''
                started = False
            else:
                response += x
        elif started:
            response += x
    yield response
for result in method('ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA'):
    print result

如果我使用min_len = 30,返回值是:

ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA

如果我使用min_len为0,返回值是:

ATGGAAGTTGGATGA

试试这个:

seq= 'ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA'
OR_0 = re.findall(r'ATG(?:.{3})*?(?:TAA|TAG|TGA)',seq) 

最新更新