Python正则表达式:如何重复模式的重复?

时间:2013-09-08 04:52:52

标签: python regex frame

我正在研究一长串DNA核苷酸,我正在寻找以起始代码'AAA'开头并以终止代码'CCC'结束的序列。由于核苷酸有三联体,我发现每个序列的起点和终点之间的核苷酸数必须是三的倍数。

例如,'AAAGGGCCC'是有效序列,但'AAAGCCC'不是。

此外,在每个停止代码之前,我想要找到关于特定阅读框的最长链。

例如,如果DNA是'AAAGGGAAACCC',那么'AAAGGGAAACCC'和'AAACCC'在技术上都是有效的,但由于它们共享相同的停止代码实例,我只想要最长的DNA链'AAAGGGAAACCC ”。另外,如果我的链是'AAAAGGCCCCC',我必须返回'AAAAGGCCC'和'AAAGGCCCC',因为它们处于不同的阅读框架中(一个阅读框架是mod 3,另一个是mod 1。)

虽然我认为我有代码来搜索满足3个要求的倍数并且不重叠的字符串,但我不确定如何实现保持相同阅读框的第二个标准。我下面的代码只返回不重叠的最长字符串,但不区分读取帧,所以在上面的例子中它会捕获'AAAAGGCCC'而不是'AAAGGCCCC':

match = re.finditer(r"AAA\w{3}{%d}BBB$"% (minNucleotide-6, math.ceil((minNucleotide-6)/3))

抱歉啰嗦,谢谢你看看!

2 个答案:

答案 0 :(得分:4)

使用positive lookahead assertion。这允许您在字符串中的每个字符处重新应用正则表达式,从而可以找到所有重叠匹配,因为前瞻断言不会消耗任何字符,如正常匹配。由于您仍需要匹配一些实际文本,因此您可以使用capturing group

由于re.findall()返回捕获组的内容而不是完整的正则表达式匹配(全部为''),因此您可以使用:

>>> import re
>>> re.findall(r"(?=(AAA(?:\w{3})*?CCC))", "AAAAGGCCCC")
['AAAAGGCCC', 'AAAGGCCCC']

作为一个评论过的Python函数:

def find_overlapping(sequence):
    return re.findall(
    """(?=        # Assert that the following regex could be matched here:
     (            # Start of capturing group number 1.
      AAA         # Match AAA.
      (?:         # Start of non-capturing group, matching...
       [AGCT]{3}  # a DNA triplet
      )*?         # repeated any number of times, as few as possible.
      CCC         # Match CCC.
     )            # End of capturing group number 1. 
    )             # End of lookahead assertion.""", 
    sequence, re.VERBOSE)

答案 1 :(得分:1)

想到的最简单的模式是:

'AAA(\w{3})*CCC'
            ^^^ stop code
           ^ zero or more of…
    ^     ^ a group of…
     ^^^^^ three characters
 ^^^ start code

如果您对三个字符组的数量有其他要求,例如“至少两个此类组”,您现在可以轻松地将正则表达式中的星形字符替换为您需要的字符。

至于最长的比赛和不同的比赛,我不确定。从技术上讲,明星角色已经贪婪,这将匹配可能的最长字符串,因此应该满足您的要求。但是我担心这个功能以及在单个帧中不共享子串的要求会很糟糕地进行交互。

我认为最明确的方法是要求正则表达式引擎为您提供所有匹配,无论长度和帧数(只要内部部分的长度可被3整除),然后在正则表达式之外排除情况。 / p>

如果你真的想使用正则表达式引擎来实现这一点,我可以想到一种方法 - 通过运行特定的正则表达式三次,每帧一次。这些正则表达式将是:

^(?:\w{3})*AAA(\w{3})*CCC
^(?:\w{3})*\wAAA(\w{3})*CCC
^(?:\w{3})*\w\wAAA(\w{3})*CCC

如您所见,它们中的每一个首先匹配3k,3k + 1或3k + 2个字符 - 这样AAA起始代码将从不同的帧开始。要获得匹配的部分,您需要检查返回的匹配对象。我真的不知道重叠序列会发生什么。