我需要解析一些特殊的数据结构.它们有点像C格式,看起来大致如下:
Group("GroupName") { /* C-Style comment */ Group("AnotherGroupName") { Entry("some","variables",3.141); Entry("other",1,2.718); } Entry("linebreaks","allowed",3,1.414 ); }
我可以想到几种方法来解决这个问题.我可以使用正则表达式“代码化”代码.我可以一次读取一个字符的代码,并使用状态机来构建我的数据结构.我可以摆脱逗号界线并逐行阅读.我可以编写一些转换脚本,将此代码转换为可执行的Python代码.
是否有一个很好的pythonic方法来解析这样的文件?
你会如何解析它?
这是关于如何解析字符串的一般问题,而不是关于这种特定文件格式的问题.
解决方法
@H_502_14@ 使用pyparsing(Mark Tolonen,当你的帖子通过时我刚刚点击“Submit Post”),这非常简单 – 请参阅下面代码中嵌入的注释:data = """Group("GroupName") { /* C-Style comment */ Group("AnotherGroupName") { Entry("some",3.141); Entry("other",2.718); } Entry("linebreaks",1.414 ); } """ from pyparsing import * # define basic punctuation and data types LBRACE,RBRACE,LPAREN,RPAREN,SEMI = map(Suppress,"{}();") GROUP = Keyword("Group") ENTRY = Keyword("Entry") # use parse actions to do parse-time conversion of values real = Regex(r"[+-]?\d+\.\d*").setParseAction(lambda t:float(t[0])) integer = Regex(r"[+-]?\d+").setParseAction(lambda t:int(t[0])) # parses a string enclosed in quotes,but strips off the quotes at parse time string = QuotedString('"') # define structure expressions value = string | real | integer entry = Group(ENTRY + LPAREN + Group(Optional(delimitedList(value)))) + RPAREN + SEMI # since Groups can contain Groups,need to use a Forward to define recursive expression group = Forward() group << Group(GROUP + LPAREN + string("name") + RPAREN + LBRACE + Group(ZeroOrMore(group | entry))("body") + RBRACE) # ignore C style comments wherever they occur group.ignore(cStyleComment) # parse the sample text result = group.parseString(data) # print out the tokens as a nice indented list using pprint from pprint import pprint pprint(result.asList())
打印
[['Group','GroupName',[['Group','AnotherGroupName',[['Entry',['some','variables',3.141]],['Entry',['other',2.718]]]],['linebreaks','allowed',1.4139999999999999]]]]]
(不幸的是,由于pyparsing定义了一个“Group”类,用于将结构赋予解析的标记,因此可能存在一些混淆 – 请注意条目中的值列表如何分组,因为列表表达式包含在一个pyparsing Group中.)