0

为什么我的模式会产生这个结果?我希望它会找到ATG一个不包括 3 的序列TAA

In [102]: s = 'GATGCCTAAG'
In [103]: pat = re.compile("(ATG((\w\w\w)*)(?!TAA))")
In [104]: pat.findall(s)
Out[104]: [('ATGCCTAAG', 'CCTAAG', 'AAG')]
4

3 回答 3

3

findall方法返回匹配列表。如果模式包含捕获组,则每个匹配项都是由模式中每个捕获组匹配的字符串的元组。

文档中

pattern返回in的所有非重叠匹配string,作为字符串列表。string从左到右扫描,并按找到的顺序返回匹配项。如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。空匹配包含在结果中,除非它们触及另一个匹配的开始。

您的模式包含三个捕获组。这些组是嵌套的。第一个(也是最外面的)组是整个模式,(ATG((\w\w\w)*)(?!TAA))。第二组是((\w\w\w)*)。第三组是(\w\w\w)

请注意,否定的前瞻断言 ,(?!TAA)不是捕获组。

本质上,您的模式说要匹配密码子ATG,然后是尽可能多的密码子,但如果匹配将在一个TAA密码子处停止,则备份两个密码子。由于*是贪婪的,您的模式将匹配TAA中间的密码子。如果密码子出现在输入字符串的末尾,它只会拒绝TAA密码子(以及之前的密码子) 。TAA

由于您的捕获组,您的模式表示每个返回的匹配项应包含三个字符串:匹配密码子的整个序列、匹配密码子的序列(不包括初始ATG)和序列中最后一个匹配的密码子。

您可以使用 将组标记为非捕获(?:...),如下所示:

In [5]: pat = re.compile("(?:ATG(?:(?:\w\w\w)*)(?!TAA))")

如果您的模式不包含捕获组,则将findall每个匹配项作为单个字符串返回,而不是作为元组返回。

In [6]: pat.findall(s)
Out[6]: ['ATGCCTAAG']

如果您想停在第一个 TAA,但如果根本没有,则转到字符串的末尾TAA,您需要检查每个密码子,方法是将您的否定前瞻断言放在重复中:

pat = re.compile("ATG(?:(?!TAA)\w\w\w)*")

这断言,在第一个密码子之后的每个密码子ATG,它不应该匹配一个TAA密码子。

如果您想在第一个TAA密码子处停止,即使该密码子未与 对齐ATG,您也可以这样做:

In [7]: pat = re.compile("ATG(?:(?!.{0,2}TAA)\w\w\w)*")

In [8]: pat.findall(s)
Out[8]: ['ATG']

In [10]: pat.findall('ATGCCTGAATATAAG')
Out[10]: ['ATGCCTGAA']
于 2013-11-14T23:15:19.463 回答
0

此外,在 re 模块中,除了@rob mayoff 所写的内容之外, * 可能包括该项目的零。

从文档:

*

使生成的 RE 匹配前一个 RE 的 0 个或多个重复,尽可能多的重复。ab* 将匹配 'a'、'ab' 或 'a' 后跟任意数量的 'b'。

于 2013-11-14T23:19:31.213 回答
0

我认为您最好的解决方案是制作一个非常简单的正则表达式来捕获 TAA,然后应用一个过滤器来去除 TAA 模式。

于 2013-11-14T23:22:39.863 回答