pyparsing中Word的非贪婪匹配?

时间:2016-10-08 14:28:02

标签: python pyparsing non-greedy

我希望匹配以_foo_bar结尾的字词。我写了这个:

identifier = Word(alphanums + '_')
string     = identifier + Suppress('_') + oneOf('foo bar')

不幸的是,我意识到identifier贪婪并且使用了所有关键字。

如何强迫identifier不要贪心?

$ string.parseString('a_keyword_foo')
ParseException: Expected "_" (at char 13), (line:1, col:14)

一些有效的关键字:

a_keyword_foo          # ['a_keyword', 'foo']
foo_bar_foo            # ['foo_bar',   'foo']
bar_bar                # ['bar',       'bar']

一些无效的关键字:

keyword_foo_foobar
2keywords_bar          # The leading number is perhaps another question...
foo _bar 
_foo

2 个答案:

答案 0 :(得分:2)

一旦您知道自己在寻找什么,就可以使用pp.SkipTo

In [38]: foo_or_bar = Literal('foo') | Literal('bar')

In [39]: string = SkipTo(Literal('_') + foo_or_bar) + Literal('_') + foo_or_bar

In [42]: string.parseString('frumpy _foo')
Out[42]: (['frumpy ', '_', 'foo'], {})

不幸的是,你也会遇到这种情况:

In [44]: string.parseString('frumpy _foo _foo')
Out[44]: (['frumpy ', '_', 'foo'], {})

如果图案可以出现多次。

问题是pyparsing没有前瞻性。如果您也关注第二种情况,则必须将其定义为以下划线+ foo或bar结尾的一个或多个内容(如上所述),然后选择最后一个。

答案 1 :(得分:1)

如果你必须/可以切换到re api,你可以在那里使用非贪婪匹配:

    import re
    p = re.compile (r"""([a-z_]+?)        # lazy matching identifier
                         _ (bar|foo)      # _ with foo or bar
       """, re.VERBOSE)
    subject_string = 'a_hello_foo'
    m = p.match( subject_string )
    print "groups:", m.groups()
    print "group 1:", m.group(1)

在pyparsing中也有可能使用正则表达式。