2009-08-24 34 views
0

我將如何解析以下輸入(通過線或通過正則表達式...或者兩者結合的去行):匹配數據庫輸出(平衡圓括號,表格和行結構)並將其輸出爲列表?

Table[ 
    Row[ 
     C_ID[Data:12345.0][Sec:12345.0][Type:Double] 
     F_ID[Data:17660][Sec:17660][Type:Long] 
     NAME[Data:Mike Jones][Sec:Mike Jones][Type:String] 
    ] 

    Row[ 
     C_ID[Data:2560.0][Sec:2560.0][Type:Double] 
    ... 
    ] 
] 

有壓痕在那裏,當然,因此它可以通過\拆分ñ\ T(然後清理在C_ID額外的選項卡\ t,F_ID線,這樣...

所需的輸出是蟒蛇的東西更實用:

{'C_ID': 12345, 'F_ID': 17660, 'NAME': 'Mike Jones',....} {'C_ID': 2560, ....} 

我試着去逐行,然後使用多個split()來拋棄我不知道的東西編輯和保留我所需要的,但我相信有一個更加優雅和快速的方式做它...

+0

不幸的是,我不能使用任何其他解析器,而不能使用默認Python發行版中可用的解析器......系統限制。 – 2009-08-24 22:49:25

+0

如果這是家庭作業,那麼這個限制是有道理的。如果它不是家庭作業,你只需下載一個解析器把它放到目錄樹中,然後假裝你寫了它。只要保持許可證方便,以防有人問你的驚人生產力。 – 2009-08-24 23:52:49

回答

3

解析遞歸結構與正則表達式是一個痛苦,因爲你必須保持狀態。

而是使用pyparsing或其他一些真正的解析器。

一些人喜歡PLY,因爲它遵循傳統的Lex/Yacc架構。

0

這個優秀的page列出了很多可供Python程序員使用的解析器。正則表達式不適合「平衡圓括號」匹配,但在該頁面上審閱的任何第三方包都可以很好地爲您服務。

-1

此正則表達式:

Row\[[\s]*C_ID\[[\W]*Data:([0-9.]*)[\S\W]*F_ID\[[\S\W]*Data:([0-9.]*)[\S\W]*NAME\[[\S\W]*Data:([\w ]*)[\S ]* 

第一行會匹配:

1 $ = 12345.0 $ 2 = 17660 $ 3 =麥克·瓊斯

然後你可以使用這樣的事情:

{'C_ID': $1, 'F_ID': $2, 'NAME': '$3'} 

產生:

{'C_ID': 12345.0, 'F_ID': 17660, 'NAME': 'Mike Jones'} 

所以你需要通過你的輸入迭代,直到它停止符合行... 是否有意義?

+0

順便說一句,另一種解決方案可以是將整個批次轉換爲XML並使用XSLT來構建您所需的輸出。 – DmitryK 2009-08-24 23:58:01

+0

這將工作...種。 如果我想爲每一行執行該正則表達式,以便它只將C_I​​D作爲$ 1和12345.0作爲$ 2進行匹配,然後對下一行(分別保存變量名稱和值分別爲$ 1和$ 2)重複? – 2009-08-25 06:06:18

+0

那麼你將分別需要3個不同的正則表達式用於C_ID,F_ID和NAME。我認爲你會更好地解析每行的輸入。 – DmitryK 2009-08-25 06:23:43

1

確實沒有很多不可預測的嵌套在這裏,所以你可以用正則表達式來做到這一點。但是pyparsing是我的首選工具,所以這裏是我的解決方案:

from pyparsing import * 

LBRACK,RBRACK,COLON = map(Suppress,"[]:") 
ident = Word(alphas, alphanums+"_") 
datatype = oneOf("Double Long String Boolean") 

# define expressions for pieces of attribute definitions 
data = LBRACK + "Data" + COLON + SkipTo(RBRACK)("contents") + RBRACK 
sec = LBRACK + "Sec" + COLON + SkipTo(RBRACK)("contents") + RBRACK 
type = LBRACK + "Type" + COLON + datatype("datatype") + RBRACK 

# define entire attribute definition, giving each piece its own results name 
attrDef = Group(ident("key") + data("data") + sec("sec") + type("type")) 

# now a row is just a "Row[" and one or more attrDef's and "]" 
rowDef = Group("Row" + LBRACK + Group(OneOrMore(attrDef))("attrs") + RBRACK) 

# this method will process each row, and convert the key and data fields 
# to addressable results names 
def assignAttrs(tokens): 
    ret = ParseResults(tokens.asList()) 
    for attr in tokens[0].attrs: 
     # use datatype mapped to function to convert data at parse time 
     value = { 
      'Double' : float, 
      'Long' : int, 
      'String' : str, 
      'Boolean' : bool, 
      }[attr.type.datatype](attr.data.contents) 
     ret[attr.key] = value 
    # replace parse results created by pyparsing with our own named results 
    tokens[0] = ret 
rowDef.setParseAction(assignAttrs) 

# a TABLE is just "Table[", one or more rows and "]" 
tableDef = "Table" + LBRACK + OneOrMore(rowDef)("rows") + RBRACK 

test = """ 
Table[  
    Row[ 
    C_ID[Data:12345.0][Sec:12345.0][Type:Double] 
    F_ID[Data:17660][Sec:17660][Type:Long] 
    NAME[Data:Mike Jones][Sec:Mike Jones][Type:String] 
    ]  
    Row[ 
    C_ID[Data:2560.0][Sec:2560.0][Type:Double] 
    NAME[Data:Casey Jones][Sec:Mike Jones][Type:String] 
    ] 
]""" 

# now parse table, and access each row and its defined attributes 
results = tableDef.parseString(test) 
for row in results.rows: 
    print row.dump() 
    print row.NAME, row.C_ID 
    print 

打印:

[[[['C_ID', 'Data', '12345.0', 'Sec', '12345.0', 'Type', 'Double'],... 
- C_ID: 12345.0 
- F_ID: 17660 
- NAME: Mike Jones 
Mike Jones 12345.0 

[[[['C_ID', 'Data', '2560.0', 'Sec', '2560.0', 'Type', 'Double'], ... 
- C_ID: 2560.0 
- NAME: Casey Jones 
Casey Jones 2560.0 

分配在assignAttrs給你按名稱訪問您的每一個屬性的結果名稱。要查看名稱是否被省略,只需測試「if not row.F_ID:」。