4

我有一个格式如下的配置文件:

protocol sample_thread {
    { AUTOSTART 0 }
    { BITMAP thread.gif }
    { COORDS {0 0} }
    { DATAFORMAT {
        { TYPE hl7 }
        { PREPROCS {
            { ARGS {{}} }
            { PROCS sample_proc }
        } }
    } } 
}

真实的文件可能没有这些确切的字段,我宁愿不必在解析之前向解析器描述数据的结构。

我已经寻找其他配置文件解析器,但我发现没有一个似乎能够接受这种语法的文件。

我正在寻找一个可以解析这样的文件的模块,有什么建议吗?

如果有人好奇,有问题的文件是由 Quovadx Cloverleaf 生成的。

4

8 回答 8

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']]]]]]]

从那里您可以根据需要变得更复杂(将数字与字符串分开解析,查找特定的字段名称等)。以上内容很笼统,只是寻找字符串(定义为除“{”和“}”之外的任何非空白字符)和{}分隔的字符串列表。

于 2009-06-15T14:35:14.420 回答
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 变得更快。

——保罗

于 2009-08-29T13:57:04.017 回答
1

我将尝试回答我认为缺少的问题...

配置文件有多种格式。有一些众所周知的格式,例如 *.ini 或 apache config - 这些往往有许多可用的解析器。

然后是自定义格式。这就是你的样子(它可能是你和我以前从未见过的一些明确定义的格式 - 但直到你知道那是什么并不重要)。

我会从这个软件开始,看看他们是否有一个可以加载/生成这些文件的编程 API。如果没有明显的问题,请致电 Quovadx。可能有人已经解决了这个问题。

否则,您可能需要自己创建自己的解析器。

假设您的样本代表了一个完整的示例,那么为这种格式编写解析器并不难。它是一个值层次结构,其中每个节点可以包含一个值或值的子层次结构。一旦定义了值可以包含的基本类型,解析器就是一个非常简单的结构。

您可以使用 Lex/Flex 之类的工具或仅使用您选择的语言的直接解析器相当快速地编写此代码。

于 2009-06-15T13:58:51.293 回答
1

您的配置文件与JSON非常相似(几乎将所有“{”和“}”替换为“[”和“]”)。大多数语言都有内置的 JSON 解析器(PHP、Ruby、Python 等),如果没有,也有一些库可以为您处理它。

如果您无法更改配置文件的格式,您可以将所有文件内容读取为字符串,并通过您喜欢的任何方式替换所有“{”和“}”字符。然后您可以将字符串解析为 JSON,然后您就设置好了。

于 2009-06-15T14:44:06.647 回答
1

您可以轻松地在 python 中编写脚本,将其转换为 python dict,格式看起来几乎像分层名称值对,唯一的问题似乎是 Coards {0 0},其中 {0 0} 不是名称值对,而是一个列表,所以谁知道其他这种情况的格式我认为你最好的选择是有该格式的规范并编写一个简单的 python 脚本来阅读它。

于 2009-06-15T14:18:36.940 回答
0

我在Cheese Shop上搜索了一下,但没有发现任何对你的例子有帮助的东西。检查示例页面,以及这个特定的解析器(它的语法有点像你的)。我认为这应该可以帮助您编写自己的。

于 2009-06-15T14:04:44.480 回答
0

查看LEX 和 YACC。有点学习曲线,但它们可以为任何语言生成解析器。

于 2009-06-15T14:13:24.113 回答
-2

也许您可以编写一个简单的脚本,将您的配置转换为 xml 文件,然后使用 lxml、Beatuful Soup 或其他任何东西来读取它?例如,您的转换器可以使用 PyParsing 或正则表达式。

于 2009-06-15T13:58:00.453 回答