我有一个以下格式的配置文件:
protocol sample_thread {
{ AUTOSTART 0 }
{ BITMAP thread.gif }
{ COORDS {0 0} }
{ DATAFORMAT {
{ TYPE hl7 }
{ PREPROCS {
{ ARGS {{}} }
{ PROCS sample_proc }
} }
} }
}
真实文件可能没有这些确切的字段,我宁愿在解析之前不必描述数据的结构是解析器。
我已经找了其他配置文件解析器,但我发现没有一个能够接受这种语法的文件。
我正在寻找一个可以解析这样的文件的模块,有什么建议吗?
如果有人好奇,有问题的文件是由Quovadx Cloverleaf生成的。
答案 0 :(得分:11)
pyparsing对于快速简单的解析非常方便。最低限度的是:
import pyparsing
string = pyparsing.CharsNotIn("{} \t\r\n")
group = pyparsing.Forward()
group << pyparsing.Group(pyparsing.Literal("{").suppress() +
pyparsing.ZeroOrMore(group) +
pyparsing.Literal("}").suppress())
| string
toplevel = pyparsing.OneOrMore(group)
用它作为:
>>> toplevel.parseString(text)
['protocol', 'sample_thread', [['AUTOSTART', '0'], ['BITMAP', 'thread.gif'],
['COORDS', ['0', '0']], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS',
[['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]]
从那里你可以根据需要变得更复杂(从字符串中单独解析数字,查找特定的字段名称等)。以上是非常通用的,只是寻找字符串(定义为除“{”和“}”之外的任何非空格字符)和{}分隔的字符串列表。
答案 1 :(得分:2)
将Brian的pyparsing解决方案再迈出一步,您可以使用Dict类为此格式创建一个准解串器:
import pyparsing
string = pyparsing.CharsNotIn("{} \t\r\n")
# use Word instead of CharsNotIn, to do whitespace skipping
stringchars = pyparsing.printables.replace("{","").replace("}","")
string = pyparsing.Word( stringchars )
# define a simple integer, plus auto-converting parse action
integer = pyparsing.Word("0123456789").setParseAction(lambda t : int(t[0]))
group = pyparsing.Forward()
group << ( pyparsing.Group(pyparsing.Literal("{").suppress() +
pyparsing.ZeroOrMore(group) +
pyparsing.Literal("}").suppress())
| integer | string )
toplevel = pyparsing.OneOrMore(group)
sample = """
protocol sample_thread {
{ AUTOSTART 0 }
{ BITMAP thread.gif }
{ COORDS {0 0} }
{ DATAFORMAT {
{ TYPE hl7 }
{ PREPROCS {
{ ARGS {{}} }
{ PROCS sample_proc }
} }
} }
}
"""
print toplevel.parseString(sample).asList()
# Now define something a little more meaningful for a protocol structure,
# and use Dict to auto-assign results names
LBRACE,RBRACE = map(pyparsing.Suppress,"{}")
protocol = ( pyparsing.Keyword("protocol") +
string("name") +
LBRACE +
pyparsing.Dict(pyparsing.OneOrMore(
pyparsing.Group(LBRACE + string + group + RBRACE)
) )("parameters") +
RBRACE )
results = protocol.parseString(sample)
print results.name
print results.parameters.BITMAP
print results.parameters.keys()
print results.dump()
打印
['protocol', 'sample_thread', [['AUTOSTART', 0], ['BITMAP', 'thread.gif'], ['COORDS',
[0, 0]], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]]
sample_thread
thread.gif
['DATAFORMAT', 'COORDS', 'AUTOSTART', 'BITMAP']
['protocol', 'sample_thread', [['AUTOSTART', 0], ['BITMAP', 'thread.gif'], ['COORDS', [0, 0]], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]]
- name: sample_thread
- parameters: [['AUTOSTART', 0], ['BITMAP', 'thread.gif'], ['COORDS', [0, 0]], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]
- AUTOSTART: 0
- BITMAP: thread.gif
- COORDS: [0, 0]
- DATAFORMAT: [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]
我认为通过pyparsing你会得到更快的速度。
- 保罗
答案 2 :(得分:1)
我会尝试回答我认为缺失的问题...
配置文件有多种格式。有众所周知的格式,如* .ini或apache配置 - 这些格式往往有很多解析器可用。
然后有自定义格式。这就是你的看法(它可能是你以前从未见过的一种定义明确的格式 - 但直到你知道它是什么并不重要)。
我会从这个来自的软件开始,看看他们是否有可以加载/生成这些文件的编程API。如果没有什么是显而易见的,请给Quovadx打电话。有可能有人已经解决了这个问题。
否则你可能会自己创建自己的解析器。
假设您的样本代表完整的示例,为此格式编写解析器并不是非常困难。它是值的层次结构,其中每个节点可以包含值的值或子层次结构。一旦定义了值可以包含的基本类型,解析器就是一个非常简单的结构。
你可以使用像Lex / Flex这样的东西或者用你选择的语言中的直接解析器来快速写出来。
答案 3 :(得分:1)
你可以轻松地在python中编写一个脚本,将其转换为python dict,格式看起来几乎像分层名称值对,只有问题似乎是 Coards {0 0},其中{0 0}不是名称值对,而是列表 那么谁知道格式中还有其他类似的案例 我认为你最好的选择是为这种格式制作规范并编写一个简单的python脚本来阅读它。
答案 4 :(得分:1)
您的配置文件与JSON非常相似(几乎用“[”和“]”替换所有“{”和“}”)。大多数语言都有内置的JSON解析器(PHP,Ruby,Python等),如果没有,可以使用库来处理它。
如果您无法更改配置文件的格式,则可以将所有文件内容作为字符串读取,并通过您喜欢的任何方式替换所有“{”和“}”字符。然后你可以将字符串解析为JSON,然后设置。
答案 5 :(得分:0)
我在Cheese Shop上搜索了一下,但我找不到任何有用的例子。检查Examples页面和this特定解析器(它的语法类似于你的)。我认为这应该可以帮助你自己编写。
答案 6 :(得分:0)
查看LEX and YACC。有点学习曲线,但他们可以为任何语言生成解析器。
答案 7 :(得分:-2)
也许您可以编写一个简单的脚本,将您的配置转换为xml文件,然后使用lxml,Beatuful Soup或其他任何东西读取它?例如,您的转换器可以使用PyParsing或正则表达式。