Python 如何解析非唯一位置模式?
我有两个问题与解析一个令人讨厌的模式有关。以下是一些无意义的例子:Python 如何解析非唯一位置模式?,python,python-3.x,pyparsing,Python,Python 3.x,Pyparsing,我有两个问题与解析一个令人讨厌的模式有关。以下是一些无意义的例子: color ::= word composed of alphas colors ::= (color | '(' color ')' )... comments ::= '(' structure ';' ... ')' 示例=[ "", “红绿”, “#1#红绿”, “#1#红绿”, “#1,2#红绿”, “红绿()”, “#1#红绿色(蓝色)”, “#1#红绿色(#5#蓝色)”, “#1#红绿色(#5#蓝色)”, “#
color ::= word composed of alphas
colors ::= (color | '(' color ')' )...
comments ::= '(' structure ';' ... ')'
示例=[
"",
“红绿”,
“#1#红绿”,
“#1#红绿”,
“#1,2#红绿”,
“红绿()”,
“#1#红绿色(蓝色)”,
“#1#红绿色(#5#蓝色)”,
“#1#红绿色(#5#蓝色)”,
“#1,2#红绿#5#蓝(紫)#7#黄”,
“#1,2#红色(栗色)绿色(#5#蓝色(紫色)#7#黄色)”,
]
在这一点上,我应该说我无法控制这些字符串的创建
正如您所看到的,基本上我想要解析的每个模式都是可选的。然后是我想捕捉的不同部分。我将这些示例的结构视为:
[cars] [colors] [comments] [buyers]
其中,注释
由子结构组成,可以是用分号分隔的倍数
comments: ([cars] [colors] [buyers]; ...)
为了捕获内容,我创建了以下语法:
将pyparsing导入为pp
整数=pp.py\u common.integer
car_ref=“#”+pp.Group(pp.delimitedList(整数))(“cars”)+“#”
买方_ref=“”
我的问题是:
颜色
的内容,而不是注释
将>编码为分隔符并将其拆分。然而,我没有执行这一战略。我尝试的是:
sub_注释=(
pp.可选(车辆参考)+
pp.Group(pp.ZeroOrMore(pp.Regex(r“[^;#\s]”))(“颜色”)+
pp.可选(买方参考)
)
拆分注释=pp.Optional(pp.delimitedList(
pp.Group(次级注释)(“注释*”),
delim=“;”
))
def parse_注释(原始、位置、标记):
#去掉括号。
返回split_comments.transformString(原始[tokens[0]+1:tokens[2]-1])
comments=pp.originalTextFor(pp.nestedExpr()).setParseAction(parse_comments)
当我使用这个字符串时,所有内容都会变成一个连续的字符串,可能是因为外部pp.originalTextFor
res=comments.parseString((#5#蓝色(紫色)#7#黄色),parseAll=True)
编辑:
以最后一个字符串示例为例,我希望最终得到一个如下所示的对象结构:
{
"cars": [1, 2],
"colors": "red (maroon) green",
"buyers": [2, 3],
"comments": [
{
"cars": [5],
"colors": "blue (purple)",
"buyers": [6]
},
{
"cars": [7],
"colors": "yellow",
"buyers": [10]
}
]
}
因此,
colors
部分中的括号应该按照顺序进行维护,就像散文一样。括号介绍了注释
部分,我不关心它们的顺序,也不关心单个注释的顺序。我想你已经准备好了大部分内容,你只是在努力处理递归部分,注释本身可以包含子结构,包括更多注释
您将此作为您的BNF:
structure ::= [cars] [colors] [comments] [buyers]
cars ::= '#' integer, ... '#'
buyers ::= '<' integer, ... '>'
我接受了你对汽车和买家的定义,并为评论添加了颜色和递归定义。然后进行了从BNF到pyparsing表达式的相当机械的转换:
integer = pp.pyparsing_common.integer
car_ref = "#" + pp.Group(pp.delimitedList(integer))("cars") + "#"
buyer_ref = "<" + pp.Group(pp.delimitedList(integer))("buyers") + ">"
# not sure if this will be sufficient for color, but it works for the given examples
color = pp.Word(pp.alphas)
colors = pp.originalTextFor(pp.OneOrMore(color | '(' + color + ')'))("colors")
# define comment placeholder so it can be used in definition of structure
comment = pp.Forward()
structure = pp.Group(pp.Optional(car_ref)
+ pp.Optional(colors)
+ pp.Optional(comment)("comments")
+ pp.Optional(buyer_ref))
# now insert the definition of a comment as a delimited list of structures; this takes care of
# any nesting of comments within comments
LPAREN, RPAREN = map(pp.Suppress, "()")
comment <<= pp.Group(LPAREN + pp.Optional(pp.delimitedList(structure, delim=';')) + RPAREN)
如果使用asDict()
将所有解析结果转换为常规Python dict,则会得到:
structure.runTests(examples, comment=None,
postParse=lambda test, results: results[0].asDict()
)
red green
{'colors': 'red green'}
#1# red green
{'cars': [1], 'colors': 'red green'}
#1# red green <2>
{'colors': 'red green', 'cars': [1], 'buyers': [2]}
#1,2# red green <2,3>
{'colors': 'red green', 'cars': [1, 2], 'buyers': [2, 3]}
red green ()
{'comments': [[]], 'colors': 'red green'}
#1# red green (blue)
{'cars': [1], 'colors': 'red green (blue)'}
#1# red green (#5# blue) <2>
{'colors': 'red green', 'cars': [1], 'comments': [{'cars': [5], 'colors': 'blue'}], 'buyers': [2]}
#1# red green (#5# blue <6>) <2>
{'colors': 'red green', 'cars': [1], 'comments': [{'colors': 'blue', 'cars': [5], 'buyers': [6]}], 'buyers': [2]}
#1,2# red green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
{'colors': 'red green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}
#1,2# red (maroon) green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
{'colors': 'red (maroon) green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}
structure.runTests(示例,注释=None,
postParse=lambda测试,结果:结果[0]。asDict()
)
红绿
{'colors':'red green'}
#1#红绿
{'cars':[1],'colors':'red-green'}
#1#红绿
{'colors':'red green','cars':[1],'bullers':[2]}
#1,2#红绿色
{'colors':'red green','cars':[1,2],'bullers':[2,3]}
红绿()
{'comments':[[]],'colors':'red-green'}
#1#红绿色(蓝色)
{'cars':[1],'colors':'red-green(blue)}
#1#红绿(#5#蓝)
{'colors':'red-green','cars':[1],'comments':[{'cars':[5],'colors':'blue'}],'bullers':[2]}
#1#红绿(#5#蓝)
{'colors':'red-green','cars':[1],'comments':[{'colors':'blue','cars':[5],'bullers':[6]}],'bullers':[2]}
#1,2#红绿#5#蓝(紫)#7#黄#
{'colors':'red green','cars':[1,2],'comments':[{'colors':'blue(purple)','cars':[5],'businers':[6]},{'colors':'yellow','cars':[7],'businers':[10],'businers':[2,3]}
#1,2#红色(栗色)绿色(#5#蓝色(紫色)#7#黄色)
{'colors':'red(褐红色)green','cars':[1,2],'comments':[{'colors':'blue(紫色)','cars':[5],'bullers':[6],{'colors':'yellow','cars':[7],'bullers':[10],'bullers':[2,3]}
nested_expr
是一条捷径,当你真的不想解析内容时,你只想跳过它们,但你必须考虑嵌套的打开器和关闭器。尝试将注释定义为Forward(),然后使用“当遇到注释时,它是否必须在周围元素中保持其顺序?”?或者你可以简单地报告“在这个级别上,有这些颜色和这些评论”?或者它与前面或下面的元素有关联吗?谢谢你再次回答:)所以这不是一个很好的讨论媒介。我可以在gitter.im上给你写信,或者在pyrepo上发布一个问题吗?或者你更喜欢子reddit?来回答你关于关联性的问题:不幸的是,括号有一个双重功能。它们可以引入注释部分,也可以用作散文中的普通括号。请参阅我的编辑以获得进一步的澄清。如果您想进一步了解,让我们尝试使用sub-reddit。这完美地解析了示例。谢谢你详尽的答复。
structure.runTests(examples, comment=None,
postParse=lambda test, results: results[0].asDict()
)
red green
{'colors': 'red green'}
#1# red green
{'cars': [1], 'colors': 'red green'}
#1# red green <2>
{'colors': 'red green', 'cars': [1], 'buyers': [2]}
#1,2# red green <2,3>
{'colors': 'red green', 'cars': [1, 2], 'buyers': [2, 3]}
red green ()
{'comments': [[]], 'colors': 'red green'}
#1# red green (blue)
{'cars': [1], 'colors': 'red green (blue)'}
#1# red green (#5# blue) <2>
{'colors': 'red green', 'cars': [1], 'comments': [{'cars': [5], 'colors': 'blue'}], 'buyers': [2]}
#1# red green (#5# blue <6>) <2>
{'colors': 'red green', 'cars': [1], 'comments': [{'colors': 'blue', 'cars': [5], 'buyers': [6]}], 'buyers': [2]}
#1,2# red green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
{'colors': 'red green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}
#1,2# red (maroon) green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
{'colors': 'red (maroon) green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}