无法获取正则表达式来捕获最后一组

时间:2011-11-02 02:36:04

标签: python regex bioinformatics

我正在尝试在python中编写一个正则表达式来解析一个Newick树,但是对于我的生活,我无法得到它的最后一部分来匹配。我需要解析三种类型的Newick格式:

((A,B),C);
((A:0.1,B:0.2),C:0.3);
((A:[c1]0.1,B:[c2]0.2),C:[c2]0.3);

...每个都包含三个标签(A,B,C)和各种其他信息。我想得到三个标签。这是我的正则表达式:

regex = re.compile(r"""
(
    ([,(])              # boundary
    ([A-Z0-9_\-\.]+)    # label
    (:)?                # optional colon
    (\[.+?\])?          # optional comment chunk
    (\d+\.\d+)?         # optional branchlengths
    ([),])              # end!
)
""", re.IGNORECASE + re.VERBOSE + re.DOTALL)

...但是,我只得到A和C.从来没有B.我已经跟踪到最后一个捕获组([),]的故障 - 如果我删除它,那么我得到所有的A,B和C.请帮忙 - 这里出了什么问题?!

2 个答案:

答案 0 :(得分:3)

问题可能在于您正在寻找正则表达式的非重叠实例。 类似findall的方法不会返回B,因为A的匹配会消耗,之前的B

>>> regex.findall("((A:[c1]0.1,B:[c2]0.2),C:[c2]0.3);")
[('(A:[c1]0.1,', '(', 'A', ':', '[c1]', '0.1', ','), (',C:[c2]0.3)', ',', 'C', ':', '[c2]', '0.3', ')')]

将结束模式更改为向前看(以便它不消耗任何东西)可以解决问题。

>>> regex = re.compile(r"""
... (
...     ([,(])              # boundary
...     ([A-Z0-9_\-\.]+)    # label
...     (:)?                # optional colon
...     (\[.+?\])?          # optional comment chunk
...     (\d+\.\d+)?         # optional branchlengths
...     (?=[),])            # end!
... )
... """, re.IGNORECASE + re.VERBOSE + re.DOTALL)
>>>
>>> regex.findall("((A:[c1]0.1,B:[c2]0.2),C:[c2]0.3);")
[('(A:[c1]0.1', '(', 'A', ':', '[c1]', '0.1'), (',B:[c2]0.2', ',', 'B', ':', '[c2]', '0.2'), (',C:[c2]0.3', ',', 'C', ':
', '[c2]', '0.3')]
>>>

否则,您可以迭代地使用findall并使用search参数使用pos,而不是使用>>> x = "((A:[c1]0.1,B:[c2]0.2),C:[c2]0.3);" >>> r = [] >>> index = 0 >>> while True: ... m = regex.search(x, index) ... if not m: ... break ... r.append(m.groups()) ... index = m.end(7)-1 ... >>> r [('(A:[c1]0.1,', '(', 'A', ':', '[c1]', '0.1', ','), (',B:[c2]0.2)', ',', 'B', ':', '[c2]', '0.2', ')'), (',C:[c2]0.3)', ',', 'C', ':', '[c2]', '0.3', ')')]

这样的事情:

{{1}}

答案 1 :(得分:0)

如果您只需要标签,那么您是否只能使用像[(,]([A-Z])这样的简单正则表达式?

import re

text = ["((A,B),C);",
        "((A:0.1,B:0.2),C:0.3);",
        "((A:[c1]0.1,B:[c2]0.2),C:[c2]0.3);"]

for line in text:
    labels = re.findall(r'[(,]([A-Z])', line)
    print labels

<强>结果:

['A', 'B', 'C']
['A', 'B', 'C']
['A', 'B', 'C']