2015-06-18 15 views
3

我有一个字符串组成的单词列表,我试图用pyparsing解析。非贪婪列表解析与pyparsing

该列表总是有至少三个项目。从这我想pyparsing生成三个组,其中第一个包含所有单词到最后两个项目,最后两个组应该是最后两个项目。例如:

"one two three four" 

应该解释为类似的东西:

["one two"], "three", "four" 

我可以用正则表达式做到这一点:

import pyparsing as pp 
data = "one two three four" 
grammar = pp.Regex(r"(?P<first>(\w+\W?)+)\s(?P<penultimate>\w+) (?P<ultimate>\w+)") 
print(grammar.parseString(data).dump()) 

这给:

['one two three four'] 
- first: one two 
- penultimate: three 
- ultimate: four 

我问题是我没有得到相同的结果LT与非正则表达式ParserElement的,因为pyparsing贪婪的本性,例如以下:

import pyparsing as pp 
data = "one two three four" 
word = pp.Word(pp.alphas) 
grammar = pp.Group(pp.OneOrMore(word))("first") + word("penultimate") + word("ultimate") 
grammar.parseString(data) 

失败的回溯:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/site-packages/pyparsing.py", line 1125, in parseString 
    raise exc 
pyparsing.ParseException: Expected W:(abcd...) (at char 18), (line:1, col:19) 

因为一次或更多吸食所有在列表中的单词。我迄今为止尝试用FollowedBy或NotAny防止这种贪婪行为的尝试都失败了 - 我有什么建议可以获得所需的行为?

回答

2

那么,你的OneOrMore表达式只需要一点点收紧 - 你在FollowedBy的正确轨道上。你不是真的只想OneOrMore(单词),你想要的是“OneOrMore(至少跟着2个单词的单词)”。要添加这种超前的向pyparsing,你甚至可以使用新的“*”乘法运算符来指定先行计数:

grammar = pp.Group(pp.OneOrMore(word + pp.FollowedBy(word*2)))("first") + word("penultimate") + word("ultimate") 

现在倾销这一点得到期望的:对于

[['one', 'two'], 'three', 'four'] 
- first: ['one', 'two'] 
- penultimate: three 
- ultimate: four 
+0

非常感谢你的答案,我失败了,因为我在OneOrMore之外添加了FollowedBy,例如: pp.OneOrMore(word)pp.FollowedBy(word + word) –