2009-08-24 18 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:”。