3

您如何使以下正则表达式用于 pyparsing?它应该返回给定正则表达式的令牌列表。

任何帮助将不胜感激!谢谢!

shell中的python正则表达式示例:

>>> re.split("(\w+)(lab)(\d+)", "abclab1", 3)
>>> ['', 'abc', 'lab', '1', '']

我在 pyparsing 中尝试了这个,但我似乎无法弄清楚如何正确处理它,因为第一个匹配是贪婪的,即第一个标记将'abclab'代替两个标记'abc''lab'.

pyparsing 示例(高级,即非工作代码):

name = 'abclab1'
location = Word(alphas).setResultsName('location')
lab = CaselessLiteral('lab').setResultsName('environment')
identifier = Word(nums).setResultsName('identifier')
expr = location + lab + identifier
match, start, end = expr.scanString(name).next()
print match.asDict()
4

2 回答 2

7

Pyparsing 的类几乎是从左到右的,使用显式表达式实现前瞻,如 FollowedBy(用于正前瞻)和 NotAny 或“~”运算符(用于负前瞻)。这使您可以检测通常与正在重复的项目匹配的终止符。例如,OneOrMore(Word(alphas)) + Literal('end')永远不会在诸如“start blah blah end”之类的字符串中找到匹配项,因为终止的“end”将被 OneOrMore 中的重复表达式所吞噬。解决方法是在重复的表达式中添加负前瞻:OneOrMore(~Literal('end') + Word(alphas)) + Literal('end')- 也就是说,在阅读另一个由字母组成的单词之前,首先确保它不是单词“end”。

当重复在 pyparsing 类(如 Word)中时,这种情况就会崩溃。Word(alphas)只要没有空格来停止单词,它将继续读取字母字符。您将不得不使用非常昂贵的东西来打破这种重复,例如Combine(OneOrMore(~Literal('lab') + Word(alphas, exact=1)))- 我说昂贵,因为使用复杂的组合表达式组合简单标记会使解析器变慢。

您可以通过使用包装在 pyparsing Regex 对象中的正则表达式来妥协:

>>> labword = Regex(r'(\w+)(lab)(\d+)')
>>> print labword.parseString("abclab1").dump()
['abclab1']

这会进行正确的分组和检测,但不会暴露组本身。为此,为每个组添加名称 - pyparsing 会将这些名称视为结果名称,并允许您访问各个字段,就像您调用了 setResultsName 一样:

>>> labword = Regex(r'(?P<locn>\w+)(?P<env>lab)(?P<identifier>\d+)')
>>> print labword.parseString("abclab1").dump()
['abclab1']
- env: lab
- identifier: 1
- locn: abc
>>> print labword.parseString("abclab1").asDict()
{'identifier': '1', 'locn': 'abc', 'env': 'lab'}

我能想到的唯一其他非正则表达式方法是定义一个表达式来读取整个字符串,然后在解析操作中分解各个部分。

于 2012-06-20T12:53:04.900 回答
0

如果你去掉子组符号(括号),你会得到正确的答案:)

>>> re.split("\w+lab\d+", "abclab1")
['', '']
于 2012-06-20T09:30:04.387 回答