2013-03-27 71 views
1

爲了能夠添加/刪除/修改軟件配置,我需要解析一個配置文件文件,該文件由多個塊這樣的格式文本:將文本文件內容解析爲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

回答

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 "}" 
+0

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

+0

@Jim到目前爲止工作很好,你有什麼特別的問題嗎? – SpankMe 2013-07-26 07:33:18