匹配数据库输出(平衡括号、表格和行结构)并输出为列表?
我想知道怎么处理下面的输入(可以逐行处理,也可以用正则表达式,或者两者结合):
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]
...
]
]
里面有缩进,所以可以通过 \n\t 来分割(然后再清理一下 C_ID、F_ID 行中的多余制表符 \t 等等...)
我想要的输出是更适合在 Python 中使用的格式:
{'C_ID': 12345, 'F_ID': 17660, 'NAME': 'Mike Jones',....} {'C_ID': 2560, ....}
我试过逐行处理,然后用多个 splits() 来丢掉不需要的部分,保留需要的部分,但我相信还有更优雅、更快速的方法可以做到这一点...
4 个回答
0
这个很棒的页面列出了许多适合Python程序员使用的解析器。正则表达式不太适合用来匹配“平衡的括号”,不过页面上提到的那些第三方包都能很好地满足你的需求。
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:”就可以了。