我是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'对象不可调用。
在这里,我可能真的很胖,但请其中一位专家请您直言不讳。
谢谢
史蒂夫
最佳答案
pyparsing的基本概念之一是,它不仅仅适用于字符串列表,而且还可以将解析后的片段组合成一个ParseResults对象。 ParseResults是在pyparsing中定义的丰富数据类型,如果已经从具有定义的结果名称的ParserElement中解析了 token ,则可以作为列表或dict或对象访问。
但是,尽管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']
组合用于将单独的字母和数字重新组合成字符串,否则每个匹配项都类似于
['a','2'], ['b','5']
等。(通常,searchString返回一个ParseResults对象的列表,该列表看起来像一个单元素列表的列表。通过将searchString的结果传递给
sum
,这会将它们全部添加到一个字符串的ParseResults中。)关于python - Pyparsing新手setParseAction修改 token ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13659972/