1

ソフトウェア構成を追加/削除/変更できるようにするには、構成ファイルファイルを解析する必要があります。これは、次のような形式のテキストの複数のブロックによって定義されます。

portsbuild {
        path = /jails/portsbuild;
        allow.mount;
        mount.devfs;
        host.hostname = portsbuild.home;
        ip4.addr = 192.168.0.200;
        interface = nfe0;
        exec.start = "/bin/sh /etc/rc";
        exec.stop = "/bin/sh /etc/rc.shutdown";
}

ブロックはかなり反復的であり、これまでのところ、変数の値のみが変更されています。

モジュールを使ってみましreたが、コードが肥大化して複雑になりすぎていました。次に、モジュールを試してみましたがiscpy、コードは驚くほど単純でした(ファイル全体を便利な辞書に変換するための1行)が、解析されたデータは正確に本来あるべきものではありませんでした。

>>> conf = iscpy.ParseISCString(open('/etc/jail.conf', 'r').read())
>>> conf
{'portsbuild': {'allow.mount': True, 'interface = nfe0': True, 'exec.start = "/bin/sh /etc/rc"': True, 'ip4.addr': '= 192.168.0.200', 'exec.stop': '= "/bin/sh /etc/rc.shutdown"', 'exec.stop = "/bin/sh /etc/rc.shutdown"': True, 'ip4.addr = 192.168.0.200': True, 'path': '= /jails/portsbuild', 'interface': '= nfe0', 'path = /jails/portsbuild': True, 'mount.devfs': True, 'host.hostname': '= portsbuild.home', 'host.hostname = portsbuild.home': True, 'exec.start': '= "/bin/sh /etc/rc"'}}

私も運試しをしましpyparsingたが、片道だけでいいようです。それで、Pythonオブジェクトの変更後の読み取りと書き込みの両方の方法で使用できる、クリーンで理解しやすいコードを使用してそのファイルを解析する他のモジュールまたは方法があるかどうか疑問に思っていますか?

4

1 に答える 1

2

救助のためのパセリ!カスタムパーサーを記述し、同じ正確な形式の構成ファイルに簡単に変換できるPythonオブジェクトを使用して結果を作成するのが最も簡単なモジュールのようです。以下のブロックが少し大きいサンプルソリューション:

from parsley import makeGrammar, unwrapGrammar
from collections import OrderedDict

configFileGrammer = r"""

file = block+:bs end -> OrderedDict(bs)

block = ws name:b ws '{' ws members:m ws '}' ws -> (b, OrderedDict(m))

members = (setting:first (ws setting)*:rest ws -> [first] + rest) | -> []

setting = pair | flag

pair = ws name:k ws '=' ws name:v ws ';' ws -> (k, v)

flag = ws name:k ws ';' ws -> (k, True)

name = <(~('='|';'|'{') anything)+>:n -> n.strip()

"""


testSource = r"""
    portsbuild {
            path = /jails/portsbuild;
            allow.mount;
            mount.devfs;
            host.hostname = portsbuild.home;
            ip4.addr = 192.168.0.200;
            interface = nfe0;
            exec.start = "/bin/sh /etc/rc";
            exec.stop = "/bin/sh /etc/rc.shutdown";
    }

    web01 {
            path = /jails/web01;
            allow.mount;
            mount.devfs;
            host.hostname = web02.site.com;
            ip4.addr = 10.0.0.1;
            interface = eth0;
            exec.start = "/bin/sh /etc/rc";
    }

    db01 {
            path = /jails/db01;
            mount.devfs;
            host.hostname = db01.home;
            ip4.addr = 192.168.6.66;
            interface = if0;
            exec.start = "/bin/mysql";
    }


"""
ConfigFile = makeGrammar(configFileGrammer, globals(), name="ConfigFile")

config = unwrapGrammar(ConfigFile)(testSource).apply('file')[0]
for block in config:
    print "%s {" % block
    for key in config[block]:
        if config[block][key] == True:
            print "\t%s;" % key
        else:
            print "\t%s = %s;" % (key, config[block][key])
    print "}"
于 2013-03-28T09:42:40.317 に答える