2013-04-08 42 views
2

我試圖找出如何使用這個漂亮的LIB解析BIGIP配置文件... 語法應該是這樣的:如何解析F5 bigip.conf使用pyparsing

stanza :: name { content } 
name :: several words, might contain alphas nums dot dash underscore or slash 
content:: stanza OR ZeroOrMore(printable characters) 

要使事情變得複雜一些,有一個例外:

如果名稱以「規則」開頭,則內容不能是「節」

我開始用這樣的:

from pyparsing import * 
def parse(config): 
    def BNF(): 
     """ 
     Example: 
     ... 
     ltm virtual /Common/vdi.uis.test.com_80_vs { 
      destination /Common/1.2.3.4:80 
      http-class { 
       /Common/http2https 
      } 
      ip-protocol tcp 
      mask 255.255.255.255 
      profiles { 
       /Common/http { } 
       /Common/tcp { } 
      } 
      vlans-disabled 
     } 
     ... 
     """   
     lcb, rcb, slash, dot, underscore, dash = [c for c in '{}/._-'] 
     name_word = Word(alphas + nums + dot + underscore + slash + dash) 
     name = OneOrMore(name_word).setResultsName("name") 
     stanza = Forward() 
     content = OneOrMore(stanza | ZeroOrMore(OneOrMore(Word(printables)))).setResultsName("content") 
     stanza << Group(name + lcb + content + rcb).setResultsName("stanza") 
     return stanza 


    return [x for x in BNF().scanString(config)] 

上面的代碼似乎鎖定了一些無限循環。如果「名稱」以「規則」開始,那麼它也缺少排除查找「節」的要求。

+0

你能提供一些示例輸入來測試嗎?你有什麼異常? – Michael0x2a 2013-04-08 21:23:28

回答

3

OneOrMore(ZeroOrMore(OneOrMore(Word(printables)))將始終匹配,從而導致無限循環。另外,printables包含一個閉合的花括號,它被內容項所消耗,並且不再可用於該節(如果您的內容可以包括閉括號,則需要定義一些內容以便轉義它,以區分內容支架和節支架。)

要解決名稱規則,您需要另一個內容定義,一個不包含節和一個「規則規則」。

def parse(config): 
    def BNF(): 
     lcb, rcb, slash, dot, underscore, dash = [c for c in '{}/._-'] 
     printables_no_rcb = Word(printables, excludeChars=rcb) 
     name_word = Word(alphas + nums + dot + underscore + slash + dash) 
     name = OneOrMore(name_word).setResultsName("name") 
     rule = Group(Literal('rule') + name).setResultsName("name") 
     rule_content = OneOrMore(printables_no_rcb).setResultsName("content") 
     stanza = Forward() 
     content = OneOrMore(stanza | OneOrMore(printables_no_rcb)).setResultsName("content") 
     stanza << Group(rule + lcb + rule_content + rcb | name + lcb + content + rcb).setResultsName("stanza") 
     return stanza 
    return [x for x in BNF().scanString(config)]