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