Python Pyparsing新手setParseAction修改令牌

Python Pyparsing新手setParseAction修改令牌,python,pyparsing,Python,Pyparsing,我不熟悉Pyparsing(对Python也很陌生)。我已经尝试将我的问题简化为最简单的形式,以说明问题所在(到了可能根本不需要Pyparsing的程度!) 假设我有一个由字母和数字组成的字符串,比如“b7z4a2dec3”。总有一个字母,但数字是可选的。我想将其解析为单独的元素,然后对其进行处理,但是如果有一个没有数字的裸字母,则可以方便地对其进行更改,使其后面有“默认”数字1。然后我可以以一致的方式处理每个元素。我想我可以通过setparseAction来实现这一点,如下所示: from p

我不熟悉Pyparsing(对Python也很陌生)。我已经尝试将我的问题简化为最简单的形式,以说明问题所在(到了可能根本不需要Pyparsing的程度!)

假设我有一个由字母和数字组成的字符串,比如“b7z4a2dec3”。总有一个字母,但数字是可选的。我想将其解析为单独的元素,然后对其进行处理,但是如果有一个没有数字的裸字母,则可以方便地对其进行更改,使其后面有“默认”数字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'对象不可调用

在这里,我可能真的很笨,但你们中的一位专家能帮我澄清一下吗

谢谢


Steve

了解pyparsing的一个基本概念是,它不只是处理字符串列表,而是将解析后的片段组合成ParseResults对象。ParseResults是pyparsing中定义的一种丰富数据类型,可以作为列表访问,也可以作为dict或对象访问(如果存在已从具有定义结果名称的ParseRelation解析的标记)

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

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

t += ParseResults("1")
不幸的是,这将无法作为一个lambda-你可以尝试

lambda s,l,t: t.__iadd__(ParseResults("1"))
但这感觉有点太聪明了

您还可以重新考虑一下解析器,以利用可选类。将尾随数字视为可选元素,可以为其定义一个默认值,以防缺少元素。我认为你可以通过以下方式定义你想要什么:

>>> 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中。)

啊,是的,这现在非常有意义!当我打印出解析结果时,它们看起来像一个普通的列表,所以我想我可以用通常的方式追加。另外,我还忽略了一个事实,即可选允许默认设置,这提供了一个更整洁的整体解决方案。它将应用于我的实际程序,这比这里的精简版本要复杂一些。非常感谢您的帮助……也感谢Pyparsing本身!史提夫。