将文本文件内容解析为Python对象并将对象写回可解析文本文件
问题描述:
为了能够添加/删除/修改软件配置,我需要解析一个配置文件文件,该文件由多个块这样的格式文本:将文本文件内容解析为Python对象并将对象写回可解析文本文件
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
模块和代码是非常简单(一行到整个文件转换成一个方便的词典),但分析数据wasnt它到底应该是什么:
>>> 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对象后进行读取和写入操作?
答
欧芹为救援!它似乎是最容易编写自定义分析器的模块,并且使用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 "}"
你看过pylens(http://pythonhosted.org/pylens/)吗? – 2013-03-27 14:29:30
会[ConfigParser](http://docs.python.org/2/library/configparser.html)有帮助吗? – 2013-03-27 14:36:12
@SidharthShah ConfigParser,如果我是正确的,只能以某种格式使用,不幸的是,它不匹配我正在处理的内容。 – SpankMe 2013-03-27 16:29:04