Python parseString工作,scanString失败?
在parseString给出正确结果的情况下,让scanString工作时出现问题 这一顺序起作用:Python parseString工作,scanString失败?,python,pyparsing,Python,Pyparsing,在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.Com
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|字符串中的“K”前面添加“Rev.”,它就会起作用。不幸的是,第一个表达式中的前导空格是唯一标识修订字符串所必需的,否则,在本例中,“WI”将匹配
我尝试使用scanString而不是parseString,因为它返回匹配的开始和结束位置,这有助于以后的处理。问题是“或”运算符(“|”)只直接查看其左右两侧的元素。您没有正确地将语法元素分组。下面是对您的语法的进一步分解:
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.”文本标记为可选文本,而不是为parse提供仅解析修订或“Rev.”+修订的选项。这完全避免了因使用“|”运算符而产生的任何问题
别忘了PyParsing使用操作符重载来提供更好的语法,如果语法导致混乱(如本场景中),您最好只使用长格式方法调用,如“pyp.Or(a,b)”