将文本文件内容解析为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对象后进行读取和写入操作?

+0

你看过pylens(http://pythonhosted.org/pylens/)吗? – 2013-03-27 14:29:30

+0

会[ConfigParser](http://docs.python.org/2/library/configparser.html)有帮助吗? – 2013-03-27 14:36:12

+0

@SidharthShah ConfigParser,如果我是正确的,只能以某种格式使用,不幸的是,它不匹配我正在处理的内容。 – SpankMe 2013-03-27 16:29:04

欧芹为救援!它似乎是最容易编写自定义分析器的模块,并且使用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 "}" 
+0

我期待着做类似的事情。它是如何运作的? – Jiminion 2013-07-26 03:56:32

+0

@Jim到目前为止工作很好,你有什么特别的问题吗? – SpankMe 2013-07-26 07:33:18