我正在使用pyparsing来解析以下输入:
%FSLAX45Y67*%
我以字典形式出现的输出格式为:
{
'notation': 'absolute',
'zeros': 'leading',
'x': {
'integer': 4,
'decimal': 5
},
'y': {
'integer': 6,
'decimal': 7,
},
'gerber-command': 'FS'
}
我目前得到的输出是:
{
'notation': 'absolute',
'decimal': 6,
'zeros': 'leading',
'integer': 6,
'y': ([6, 6], {'integer': [(6, 0)], 'decimal': [(6, 1)]}),
'x': ([6, 6], {'integer': [(6, 0)], 'decimal': [(6, 1)]}),
'gerber-command': 'FS'
}
(请注意,我的问题不是如何使输出看起来正确,而是如何使pyparsing以我想要的方式排列数据。)
使用以下代码:
single_digit = pyp.Regex(r'(\d)').setParseAction(lambda t: int(t[0]))
cmd_format = pyp.Literal('FS')
cmd_format_opt_leading_zeros = pyp.Literal('L').setParseAction(pyp.replaceWith('leading'))
cmd_format_opt_trailing_zeros = pyp.Literal('T').setParseAction(pyp.replaceWith('trailing'))
format_zeros = ((cmd_format_opt_leading_zeros('zeros')) |
(cmd_format_opt_trailing_zeros('zeros')))
format_notation = ((cmd_format_opt_absolute('notation')) |
(cmd_format_opt_incremental('notation')))
format_data = (single_digit)('integer') + single_digit('decimal')
gformat = (inst_del +
cmd_format('gerber-command') +
format_zeros +
format_notation +
'X' + (format_data)('x') +
'Y' + (format_data)('y') +
inst_end +
inst_del)
(省略了一些微不足道的定义)。有什么建议吗?
答案 0 :(得分:2)
使用pyparsing Group将结构添加到返回的标记中。这可能会起到作用:
gformat = (inst_del +
cmd_format('gerber-command') +
format_zeros +
format_notation +
'X' + pyp.Group(format_data)('x') +
'Y' + pyp.Group(format_data)('y') +
inst_end +
inst_del)
Pyparsing的默认行为是返回一个平坦的标记列表,以便不根据以什么顺序添加的条件来猜测结构。例如,如果你有这个:
aword = Word("A")
bword = Word("B")
cword = Word("C")
preface = aword + bword
body = cword
ending = aword + bword
totalExpr = preface + body + ending
print totalExpr.parseString("AA BB CCC A B").asList()
pyparsing只返回列表
['AA', 'BB', 'CCC', 'A', 'B']
如果要应用结构(这对于保持嵌套结果名称彼此踩踏尤其重要,正如您在整数和小数的重叠中看到的那样),请使用Group:
totalExpr = Group(preface) + body + Group(ending)
给出:
[['AA', 'BB'], 'CCC', ['A', 'B']]
如果您添加结果名称,这将是这样的:
preface = aword("As") + bword("Bs")
body = cword
ending = aword("As") + bword("Bs")
totalExpr = Group(preface)("preface") + body("body") + Group(ending)("ending")
print totalExpr.parseString("AA BB CCC A B").dump()
给出:
[['AA', 'BB'], 'CCC', ['A', 'B']]
- body: CCC
- ending: ['A', 'B']
- As: A
- Bs: B
- preface: ['AA', 'BB']
- As: AA
- Bs: BB
因为前言和结尾是分组的,所以“As”和“Bs”的重复名称是分开的。
答案 1 :(得分:1)
您必须自由地使用setParseAction
来删除不需要的信息。
在format_data
中,您需要一个从single_digit
获取输出的函数,并将其转换为您想要的格式。
def _format_data(x):
return {"integer": x["integer"][0][0],
"decimal": x["decimal"][0][0]}
format_data.setParseAction(_format_data)
答案 2 :(得分:1)
有趣的是,为什么困难的问题总是以递归结束?
x=\
{
'notation': 'absolute',
'zeros': 'leading',
'x': {
'integer': 4,
'decimal': 5
},
'y': {
'integer': 6,
'decimal': 7,
},
'gerber-command': 'FS'
}
def superPrint(inidic={},indent=' '):
for k,v in inidic.items():
if isinstance(v,dict):
yield "\n%s'%s': {"%(indent,k)
for i in superPrint(v,indent+' '*(len(k)+1)):
yield i
yield "\n%s},"%indent
else:
yield "\n%s'%s': '%s',"%(indent,k,v)
print '{%s\n}'%''.join(superPrint(x))
<强>结果:强>
{
'y': {
'integer': '6',
'decimal': '7',
},
'x': {
'integer': '4',
'decimal': '5',
},
'zeros': 'leading',
'notation': 'absolute',
'gerber-command': 'FS',
}
注意,根据你对问题的描述,我不确定你是否想要一个&#34;,&#34;在字典的最后一个元素中。
尝试更深入:
x=\
{
'notation': 'absolute',
'zeros': 'leading',
'x': {
'integer': 4,
'decimal': 5
},
'y': {
'integer': 6,
'decimal': {'try':7,
'tryHarder':{'wow':8,
'seemsGood':{'wooow':9}}},
},
'gerber-command': 'FS'
}
print '{%s\n}'%''.join(superPrint(x))
SEEMS好:
{
'y': {
'integer': '6',
'decimal': {
'try': '7',
'tryHarder': {
'wow': '8',
'seemsGood': {
'wooow': '9',
},
},
},
},
'x': {
'integer': '4',
'decimal': '5',
},
'zeros': 'leading',
'notation': 'absolute',
'gerber-command': 'FS',
}