我正在尝试在 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', ')')]
