为什么不首先解析关键字,然后将其从自由文本匹配中删除?

时间:2018-12-14 06:24:46

标签: pyparsing

我以为我理解pyparsing的逻辑,但无法弄清楚为什么下面的示例失败了。

我正在尝试分析开放文本注释,在注释的开头或结尾可以提及一个产品或一组产品。产品名称也可以从注释中省略。

输出应为上述产品及其相关描述的列表。

下面是一些测试用例。解析将所有内容都标识为“描述”,而不是先提取产品(这不是底片应该做什么吗?)

我的理解有什么问题?

import pyparsing as pp

products_list = ['aaa', 'bbb', 'ccc']
products = pp.OneOrMore(' '.join(products_list))

word = ~products + pp.Word(pp.alphas)
description = pp.OneOrMore(word)

comment_expr = (pp.Optional(products("product1")) + description("description") + pp.Optional(products("product2")))

matches = comment_expr.scanString("""\
                                aaa is a good product
                                I prefer aaa
                                No comment
                                aaa bbb are both good products""")

for match in matches:
    print match

预期结果将是:

product1: aaa, description: is a good product
product2: aaa, description: I prefer
description: No comment
product1: [aaa, bbb] description: are both good products

1 个答案:

答案 0 :(得分:1)

Pyparsing在字符串和文字之间的快捷方式等效项是为了方便起见,但有时会导致意外和意外的情况。在这些行中:

products_list = ['aaa', 'bbb', 'ccc']
products = pp.OneOrMore(' '.join(products_list))

。 我很确定您希望产品能够与任何产品匹配。但是相反,OneOrMore将此作为其参数传递:

' '.join(products_list)

这纯粹是一个字符串表达式,产生 string “ aaa bbb ccc”。将其传递给OneOrMore,就是说产品是字符串“ aaa bbb ccc”的一个或多个实例。

要获得前瞻性,您需要将产品更改为:

products = pp.oneOf(products_list)

甚至更好:

products = pp.MatchFirst(pp.Keyword(p) for p in products_list)

那么,您的否定前瞻会更好。