您有一个嵌套语法,您正在尝试解析。尽管它的范围很窄,所以可以构造正则表达式 来处理它,但它会很脆弱。就像,真的脆弱。
尝试使用ast。这有点复杂,所以我会尝试通过一个例子来解释(哈哈)。如果你想要 tl;dr,请跳到中间/结尾。
我们正在列表节点中寻找一个名字,所以我们可以从那里开始。
import ast
s = "candidates(6,1,0,5,[ev(-1000,'C0009814','Stenosis','Acquired stenosis',[stenosis],[patf])])"
mod = ast.parse(s)
for node in ast.walk(mod):
if isinstance(node, ast.List):
print(node, list(ast.iter_child_nodes(node)))
<_ast.List object at 0xb3f2ddec> [<_ast.Call object at 0xb3f2de0c>, <_ast.Load object at 0xb712756c>]
<_ast.List object at 0xb3f2deec> [<_ast.Name object at 0xb3f2df0c>, <_ast.Load object at 0xb712756c>]
<_ast.List object at 0xb3f2df2c> [<_ast.Name object at 0xb3f2df4c>, <_ast.Load object at 0xb712756c>]
我们看到语法树中有三个ast.List 节点。第一个将是调用ev 的外部列表,而两个内部列表将包含那些裸露的ast.Name 节点。这就是我们想要达到的目标 - 你特别想要第二个。
tl;博士在这里跳过
我们可以让这一切变得更简单,我只是简单介绍一下我个人是如何探索这个语法树的。这是一个单一的衬里:
s = "candidates(6,1,0,5,[ev(-1000,'C0009814','Stenosis','Acquired stenosis',[stenosis],[patf])])"
mod = ast.parse(s)
[next(ast.iter_fields(node)) for node in ast.walk(mod) if isinstance(node, ast.Name)]
Out[62]: [('id', 'candidates'), ('id', 'ev'), ('id', 'stenosis'), ('id', 'patf')]
所以只需抓住最后一个元素的第二个索引,这就是你的字符串。这种方法也适用于您的其他示例:
s = "candidates(8,1,0,7,[ev(-875,'C0003501','Aortic Valve','Aortic valve structure',[aortic,valve],[bpoc])])"
mod = ast.parse(s)
[next(ast.iter_fields(node)) for node in ast.walk(mod) if isinstance(node, ast.Name)]
Out[65]:
[('id', 'candidates'),
('id', 'ev'),
('id', 'aortic'),
('id', 'valve'),
('id', 'bpoc')]
您可以使用这种方法从语法树中获取您想要的真正任何元素。只需使用ast.iter_fields 和ast.iter_child_nodes 探索ast.walk 的输出即可。