在parseString提供正确结果的情况下,让scanString工作时遇到问题。
此序列有效:
alpha_rev = pyp.Word(pyp.alphas, max=2)
num_rev = pyp.Word('123456789', max=2)
space = pyp.White(ws=" ").suppress()
revisionExpr = (
pyp.StringStart().leaveWhitespace() +
space +
pyp.Combine(alpha_rev +
pyp.Optional(num_rev)("rev"))
)
rev_string = ' K WI, This is the title'
for match_str, start, end in (
revisionExpr.scanString(rev_string, maxMatches=1)):
print match_str
['K']
有时会出现“Rev”或“Rev.”修改前;这失败了:
revisionExpr = (
pyp.StringStart().leaveWhitespace() +
space +
pyp.Combine(alpha_rev +
pyp.Optional(num_rev)("rev"))
|
pyp.CaselessLiteral("Rev") + pyp.Optional('.') +
pyp.Combine(alpha_rev +
pyp.Optional(num_rev)("rev"))
)
for match_str, start, end in (
revisionExpr.scanString(rev_string, maxMatches=1)):
print match_str
print match_str
NameError: name 'match_str' is not defined
为什么是“|”导致比赛失败?请注意,这适用于第一个和第二个示例:
revisionTokens = revisionExpr.parseString(rev_string)
如果我将最后一个例子的第二部分(在“|”之后)提取到类似第一个例子的表格中,那么如果我添加“Rev.”它就有效。在rev_string中的“K”前面。不幸的是,第一个表达式中的前导空格对于唯一标识修订字符串是必要的,否则,在此示例中,“WI”将匹配。
我正在尝试使用scanString而不是parseString,因为它返回匹配的起始位置和结束位置,这有助于稍后处理。
答案 0 :(得分:2)
问题是你的“或”运算符(“|”)只是直接在它的左边和右边看元素。您尚未正确分组语法元素。这是你的语法分解了一点:
left_expr = pyp.Combine(alpha_rev + pyp.Optional(num_rev)("rev")
right_expr = pyp.CaselessLiteral("Rev")
joined_expr = left_expr | right_expr
final_expr = (pyp.StringStart().leaveWhitespace() +
space +
joined_expr +
pyp.Optional('.') +
pyp.Combine(alpha_rev +
pyp.Optional(num_rev)("rev"))
)
正如您所看到的,这不是您想要的 - 它将查找文本“Rev”或实际修订,然后是另一个修订。表达式的固定版本如下:
revisionExpr = (
pyp.StringStart().leaveWhitespace() +
space +
(
pyp.Combine(alpha_rev +
pyp.Optional(num_rev)("rev")
)
|
(
pyp.CaselessLiteral("Rev") +
pyp.Optional('.') +
pyp.Combine(alpha_rev +
pyp.Optional(num_rev)("rev"))
)
)
)
但是,你可以使你的语法更简洁:
revisionExpr = (
pyp.StringStart().leaveWhitespace() +
space +
pyp.Suppress(
pyp.Optional(
pyp.CaselessLiteral("Rev") +
pyp.Optional('.')
)
) +
pyp.Combine(
alpha_rev +
pyp.Optional(num_rev)("rev")
)
)
在此版本中,您只标记“Rev。” text是可选的,位于预期的位置,而不是给解析提供解析修订版或“Rev.”的选项。 +修订版。这避免了使用“|”引起的任何问题操作员。
不要忘记PyParsing使用运算符重载来提供更好的语法,如果语法引起混淆(比如在这种情况下),你可能最好只使用长形式方法调用,比如“pyp.Or(a, b)”。