所以标题听起来很奇怪,因为我的问题可能很奇怪...我有一个.txt文件,其中有来自不同程序的数千行机器输出,格式如下:
candidates(6,1,0,5,[ev(-1000,'C0009814','Stenosis','Acquired stenosis',[stenosis],[patf])])
基本上我们有候选人'标志着一个元组的开始,并且' ev'标记单个元素列表中第二个元组的开头。当我从文件中读取所有这些到python时,它以字符串形式读入。但我需要一个对象,所以我可以访问元组的第n个索引。真的,我很高兴只是找到一种方法来始终从这个字符串中获取ev()元组的最后一个值,在这种情况下,' patf'。
我曾考虑过分裂','但这并不总是成功的,因为列表中的列表“[stenosis]'”有时可能具有像[反流,主动脉]这样的值。额外的','抛出列表索引1,因此返回“主动脉”'而不是' [patf]'。
如果我能澄清任何事情,或者如果我认为需要在解决这个问题之前需要说一些知识,请告诉我。非常感谢。我还在下面列出了第二个例子,它说明了分裂问题,'。
candidates(8,1,0,7,[ev(-875,'C0003501','Aortic Valve','Aortic valve structure',[aortic,valve],[bpoc])])
编辑:我想这个对象不需要是一个列表。相同格式的元组效果很好。只要我能够始终如一地为我需要的信息引用一个索引。谢谢!
编辑2:我使用python 2.7.6
答案 0 :(得分:1)
您有一个您尝试解析的嵌套语法。虽然它的范围很窄,但正构造可以构建来处理它,但它会变得脆弱。比如,真的脆弱。
尝试使用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; dr跳过
我们可以使这一切变得更加直接,我只是简单地介绍了我亲自探索这种语法树的方法。这是一个单线:
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.walk
和ast.iter_fields
来探索ast.iter_child_nodes
的输出。
答案 1 :(得分:0)
如果您的数据始终以相同的方式格式化,最快的方法是使用正则表达式(模块re
),如果您知道如何。
否则,这是一个非常难看的黑客攻击,你可以尝试解析&#34;使用eval
的数据。这是一个例子:
eval_globals = {
"candidates": lambda *args: args,
"ev": lambda *args: args,
"aortic": "aortic",
"valve": "valve",
"bpoc": "bpoc",
# Add more of the keywords you need here
}
result = eval(line, eval_globals)
答案 2 :(得分:0)
分开[。所以你可以做s.split('[')[ - 1] .split(']')[0]其中s是文件中的一行......