python - Pyparsing 新手 setParseAction 修改标记

标签 python pyparsing

我是 Pyparsing 的新手(而且是 Python 的新手)。我试图将我的问题减少到最简单的形式,以说明出了什么问题(到我可能根本不需要 Pyparsing 的地步!)

假设我有一个由字母和数字组成的字符串,例如“b7 z4 a2 d e c3”。总是有一个字母,但数字是可选的。我想将它解析成它的各个元素,然后处理它们,但是如果有一个没有数字的裸字母,更改它会很方便,以便它后面有“默认”数字 1。然后我可以以一致的方式处理每个元素。我想我可以使用 setparseAction 来做到这一点,如下所示:

from pyparsing import *
teststring = "a2 b5 c9 d e z"
expected_letter = Word("ABCDEFGabcdefgzZxy", exact=1)
expected_number = Word(nums)
letter_and_number = expected_letter + expected_number
bare_letter = expected_letter
bare_letter.setParseAction( lambda s,l,t:  t.append("1") )
elements =  letter_and_number | bare_letter
line = OneOrMore(elements)
print line.parseString(teststring)

不幸的是,t.append() 没有按照我的预期执行,即向已解析标记列表中添加一个“1”。相反,我得到一个错误:TypeError: 'str' object is not callable。

在这里,我可能真的太厚了,但是你们中的一位专家能否让我直截了当。

谢谢

史蒂夫

最佳答案

要了解 pyparsing 的一个基本概念是,它不仅仅适用于字符串列表,而是将已解析的片段组合成一个 ParseResults 对象。 ParseResults 是在 pyparsing 中定义的丰富数据类型,如果存在从具有已定义结果名称的 ParserElement 解析的标记,则可以作为列表、字典或对象访问。

但是,虽然 ParseResults 在设计时考虑到了易于访问,但它的更新方式受到限制。在 pyparsing 内部,每个匹配的表达式都会创建一个小的 ParseResults 对象;如果这是一个大表达式的一部分,该表达式将使用 += 运算符将这些片段累积到一个大的 ParseResults 中。

在您的情况下,您可以通过创建一个包含“1”的小 ParseResults 并将其添加到 t 来附加到传入的 ParseResults:

t += ParseResults("1")

不幸的是,这不能用作 lambda - 你可以试试

lambda s,l,t: t.__iadd__(ParseResults("1"))

但这感觉有点太聪明了。

您也可以稍微重新考虑一下您的解析器,以利用 Optional 类。将您的尾随数字视为一个可选元素,您可以为其定义一个默认值以在该元素丢失时提供。我认为你可以定义你想要的东西:

>>> letter = Word(alphas,exact=1)
>>> digit = Word(nums,exact=1)
>>> teststring= "a2 b5 c9 d e z"
>>> letter_and_digit = Combine(letter + Optional(digit, default="1"))
>>> print (sum(letter_and_digit.searchString(teststring)))
['a2', 'b5', 'c9', 'd1', 'e1', 'z1']

Combine 用于将单独的字母和数字重新连接成字符串,否则每个匹配看起来像 ['a','2'], ['b','5'] 等.

(通常,searchString 返回一个 ParseResults 对象的列表,它看起来像一个单元素列表的列表。通过将 searchString 的结果传递给 sum,这会将它们全部添加到一个 ParseResults 中字符串。)

关于python - Pyparsing 新手 setParseAction 修改标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13659972/

相关文章:

python - pyparsing ParseException : Expected end of line -- general questions 问题

面向编程初学者的 Python 解析器(需要德语变音)

python - pyparsing:是否可以将 lineno/col (或 startloc/endloc)添加到所有标记中?

使用pyparsing进行SQL解析

python - 如何将数据框中的列值拆分为多列

python - Selenium chromedriver 从 cron 作业失败?

python - Django - 在模板中显示当前日期和时间

python - pyparsing 以最一般的形式解析 python 函数调用

python 类方法,接收其类的对象

python - 使用 Python 比较两个不同的 csv 列时无法获取缺失的元素