pyparsing:尾随空格不匹配但仍包含在 endloc 计算中

pyparsing: Trailing whitespace is not matched but still included for endloc calculation

我正在使用 Python 3.9.5 和 pyparsing==3.0.6

我有一个场景,我需要匹配一个词(alphanum)和可选的另一个词。但是,pp.Optional() 与尾随空格相结合会导致不正确的 endloc 索引。

import pyparsing as pp


def first_match(expression, text):
    for m, s, e in expression.scanString(text, maxMatches=1):
        return {'match': m, 'start': s, 'end': e}
    return None


expr = pp.Group(
    pp.Word(pp.alphanums) +
    pp.Optional(
        pp.Word(pp.alphanums)
    )
)

在下面的测试中,一切都如我所料。整个字符串从 0 到 3 匹配。

print(first_match(expr, "one"))
# {'match': ParseResults([ParseResults(['one'], {})], {}), 'start': 0, 'end': 3}

如果我添加尾随空格,即使它们(正确)不匹配,它们也会包含在 endloc 索引计算中。所以匹配的范围是0到8:

print(first_match(expr, "one     "))
# {'match': ParseResults([ParseResults(['one'], {})], {}), 'start': 0, 'end': 8}

scanString 返回的 endloc 索引不应该总是最后一个匹配字符的索引吗?

这是预期的行为,而不是 pyparsing 2.4.7 的回归。

Optional(expr) 视为“表达式或空”。 pyparsing 将在中间的空格上前进,然后,如果没有找到表达式,则认为解析是一个成功的匹配(因为它正在寻找的 expr 不是必需的)。

要获得您正在寻找的行为,您可以使用以下格式:

expr = pp.Group(
    pp.Word(pp.alphanums) + pp.Word(pp.alphanums)
    | pp.Word(pp.alphanums)
)

如果存在第二个字母词,它将同时解析它们,如果不存在,则只解析第一个。

使用和不使用第二个值进行测试:

print(first_match(expr, "one"))
print(first_match(expr, "one     "))
print(first_match(expr, "one     two"))
print(first_match(expr, "one     two    "))

给出:

{'match': ParseResults([ParseResults(['one'], {})], {}), 'start': 0, 'end': 3}
{'match': ParseResults([ParseResults(['one'], {})], {}), 'start': 0, 'end': 3}
{'match': ParseResults([ParseResults(['one', 'two'], {})], {}), 'start': 0, 'end': 11}
{'match': ParseResults([ParseResults(['one', 'two'], {})], {}), 'start': 0, 'end': 11}