2011-04-05 58 views
4

我有一個看起來像這樣的配置文本:解析TCL般的文字

text=""" 
key1 value1 
key2 { value1 value2 } 
key3 subkey1 { 
    key1 1 
    key2 2 
    key3 { 
     value1 
    } 
} 

BLOBKEY name { 
    dont { 
     # comment 
     parse { me } 
    } 
} 

key3 subkey2 { 
    key1 value1 
} 

""" 

的值是普通字符串或引用的字符串。鑰匙只是字母串。我事先知道key2key3.subkey1.key4將持有集合,所以我可以以不同的方式處理這些路徑。同樣,我知道BLOBKEY將包含一個「轉義」配置部分。

的目標是將其轉換成看起來像這樣一本字典:

{'key1': 'value1', 
'key2': set(['value1', 'value2']), 
'key3': { 
    'subkey1': { 
     'key1': 1, 
     'key2': 2, 
     'key3': set(['value1']), 
    }, 
    'subkey2': { 
     'key1': 'value1' 
    } 
}, 
'BLOBKEY': { 
    'name': " dont {\n  # comment\n  parse { me }\n }\n" 
} 
} 

此代碼低於其分解一堆嵌套列表做了不錯的工作。

import pyparsing 
string = pyparsing.CharsNotIn("{} \t\r\n") 
group = pyparsing.Forward() 
group << ( 
      pyparsing.Group(pyparsing.Literal("{").suppress() + 
          pyparsing.ZeroOrMore(group) + 
          pyparsing.Literal("}").suppress()) | 
      string 
      ) 

toplevel = pyparsing.OneOrMore(group) 

在Python中使用pyparsing獲得結果的最佳方式是什麼?

+0

BLOBKEY如何告訴你該值不應該被解析?因爲它全部大寫?因爲它是字面的「BLOBKEY」? – PaulMcG 2011-04-08 07:58:20

+0

因爲這是字面意思。但問題是它可能出現在任何層面。也許這不是最好的例子...你可以有key.subkey.subsubkey,如果我看到這個預定義的路徑序列,我應該停止解析並閱讀它的內容,作爲原始文本在{}之間。 – jonozzz 2011-04-08 22:53:31

回答

3

這是我迄今取得的進展。它不解析原始斑點,但其他一切似乎都是正確的。

LBRA = Literal("{").suppress() 
RBRA = Literal("}").suppress() 
EOL = lineEnd.suppress() 
tmshString = Word(alphanums + '!#$%&()*+,-./:;<=>[email protected][\]^_`|~') 

tmshValue = Combine(tmshString | dblQuotedString.setParseAction(removeQuotes)) 
tmshKey = tmshString 

def toSet(s, loc, t): 
    return set(t[0]) 

tmshSet = LBRA + Group(ZeroOrMore(tmshValue.setWhitespaceChars(' '))).setParseAction(toSet) + RBRA 

def toDict(d, l): 
    if not l[0] in d: 
     d[l[0]] = {} 

    for v in l[1:]: 
     if type(v) == list: 
      toDict(d[l[0]],v) 
     else: 
      d[l[0]] = v 

def trueDefault(s, loc, t): 
    return len(t) and t or True 

singleKeyValue = Forward() 
singleKeyValue << (
      Group(
       tmshKey + (
          # A toggle value (i.e. key without value). 
          EOL.setParseAction(trueDefault) | 
          # A set of values on a single line. 
          tmshSet | 
          # A normal value or another singleKeyValue group. 
          Optional(tmshValue | LBRA + ZeroOrMore(singleKeyValue) + RBRA).setParseAction(trueDefault) 
          ) 
      ) 
) 

multiKeysOneValue = Forward() 
multiKeysOneValue << (
      Group(
       tmshKey + (
          multiKeysOneValue | 
          tmshSet | 
          LBRA + ZeroOrMore(singleKeyValue) + RBRA 
         ) 
      ) 
) 



toplevel = OneOrMore(multiKeysOneValue) 

# now parse data and print results 
data = toplevel.parseString(testData) 

h = {} 
map(lambda x:toDict(h, x), data.asList()) 
pprint(h) 
+0

假設「BLOBKEY」是一個特殊的'this-is-a-blob'關鍵字,下面是如何獲得它的匹配:'blobkeyvalue =(「BLOBKEY」+ pyparsing.Word(pyparsing.alphanums)+ pyparsing.originalTextFor(pyparsing。 nestedExpr('{','}')))'。然後將'toplevel'定義爲'OneOrMore(blobkeyvalue | multiKeysOneValue)'。這是否讓你獲得了其他的方式? – PaulMcG 2011-04-08 08:07:00