Skip to main content
 首页 » 编程设计

python之无法让正则表达式捕获最后一组

2024年08月30日36fff_TT

我正在尝试在 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. 请帮忙 - 这里出了什么问题?!

请您参考如下方法:

问题可能是您正在寻找正则表达式的非重叠实例。 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', ')')]