Python正则表达式:解析newick格式

时间:2017-08-14 05:47:59

标签: python regex

我有一个字符串:

(A\2009_2009-01-04:0.2,(A\name2\human\2007_2007:0.3,A\chicken\ird16\2016_20016:0.4)A\name3\epi66321\2001_2001-04-04:0.5)A\name_with_space\2014_2014:0.1)A\name4\66036-8a\2004_2004-12-05;

在这棵树中, names 左侧用开括号“(”,一个右括号“)或逗号括起来,右边用冒号包围': ”。也就是说,子串“A \ 2009_2009-01-04”,“A \ name2 \ human \ 2007_2007”,“A \ name3 \ epi66321 \ 2001_2001-04-04”是名称。 (这实际上是newick格式的树)。

我想找到一个正则表达式模式,找到所有名称,尽可能少地限制命名空间。将名称视为变量,例如enter image description here中的示例:

(A:0.1,B:0.2,(C:0.3,D:0.4)E:0.5)F;

其中A,B,C等可以是任何字符串。命名空间的唯一限制是名称不能包含圆括号或方括号,'&',','或':',因为这些是定义树格式的特殊字符,与逗号定义csv格式的方式相同。

奖励:有时,树中的内部节点没有标记:

(A:0.1,B:0.2,(C:0.3,D:0.4):0.5);

在这种情况下,正确返回长度为零的字符串的正则表达式会很棒。

4 个答案:

答案 0 :(得分:1)

您似乎想要提取以1 + (),开头的子字符串,然后包含除:和{之外的1 +非空格字符尽可能多地{1}},但要停留在单词边界。

使用

;

请参阅regex demo

模式详情

  • r'[(),]+([^;:]+)\b' - 角色类中的一个或多个字符:[(),]+()
  • , - 第1组:尽可能多地使用([^;:]+);以外的一个或多个字符
  • : - 字边界

Python demo

\b

输出:

import re
rx = r'[(),]+([^;:]+)\b'
s = "(A:0.1,B:0.2,(C:0.3,D:0.4)E:0.5)F;((A\\2009_2009-01-04:0.2,(A\\name2\\human\\2007_2007:0.3,A\\chicken\\ird16\\2016_20016:0.4)A\\name3\\epi66321\\2001_2001-04-04:0.5)A\\name_with_space\\2014_2014:0.1)A\\name4\\66036-8a\\2004_2004-12-05;"
res = re.findall(rx, s)
for val in res:
    print(val)

答案 1 :(得分:0)

你可以使用正则表达式

  

(\ w +)(?=:|;)

参见示例代码

import re

regex = r"(\w+)(?=:|;)"

test_str = "((B:0.2,(C:0.3,D:0.4)E:0.5)F:0.1)A;"

matches = re.finditer(regex, test_str)

for matchNum, match in enumerate(matches):
    matchNum = matchNum + 1

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

输出

  

比赛1发现在2-3:B
  比赛2在9-10:C发现   比赛3在15-16发现:D
  比赛4在21-22发现:E
  比赛5在27-28发现:F
  第6场比赛在33-34发现:A

答案 2 :(得分:0)

工作解决方案:

[(),]([A-E])(?!;)

live demo。你犯的一个错误就是逃避角色类中的角色;但在其中,他们没有特别的意义。

我还注意选择一个尾随的分号。

答案 3 :(得分:0)

pattern = re.compile(r'[(),]A/[\S]*?:')

不是最优雅的,因为我利用了所有名字都以“A /”开头的事实。对于未来的用例,这不是真的,只是当前的用例。如果有人能找到更具普遍性的解决方案,请将这个问题保持开放。