Python re.match中的不平衡括号

时间:2014-09-17 22:28:58

标签: python regex python-3.x lexical-analysis

使用re.match()遇到一个非常奇怪的问题。这是我的代码:

for rule in rules:
    # print (rule, ", ", item)
    if re.match(rule, item):
        tokenLine.append(self.ruleDictionary[rule])
        tokenLine.append("KNOWN")
        break

背景信息:

有一个包含词法规则的外部文件,格式为:

tokenName   ::  production1  |  production2  | production3

ruleDictonary是一个词典,其中的作品是映射到相关tokenName的键,rulesruleDictionary的键列表,而item是一个字符串,读。由于某些作品很容易通过正则表达式求和,例如[a-z]+\d+,因此字典键可以是正则表达式定义,也可以是此循环要查找的内容。< / p>

问题:

目前,我在运行示例定义文件和我创建的示例输入时遇到unbalanced parenthesis错误。但是,当我在print()语句之前取消注释if语句时,它完全正常。我为调试目的创建了print()语句,并没有意识到它会对程序的实际执行产生影响。我完全迷失了,并且在启用打印时不知道它为什么会起作用。

2 个答案:

答案 0 :(得分:2)

您的问题来自模式变量rule的内容。它必须包含一个括号。但在正则表达式中,括号具有特殊含义(组)。

所以你需要使用\(\)来逃避它们。你可以用:

rule.replace('(', '\(')
rule.replace(')', '\)')

如果您想了解更多信息,请在问题Unbalanced parenthesis python中提供其他信息。

答案 1 :(得分:1)

正如在@Kuhess的回答中所描述的那样,你当前的问题是你有包含paranthesis的规则并将它们用作正则表达式,但是没有逃避paranthesis(或其他正则表达式中具有特殊含义的字符,如{{ 1}})。

但是,这仍然没有解释您在尝试匹配规则之前添加*调用的行为似乎解决了问题。

我能够使用您的回购邮件中的unmatched branch重现print()错误。然后,在不改变任何事情的情况下,使用完全相同的参数进行第二次运行!

所以我仔细查看了你的代码,我很确定我知道你的代码是非确定性的原因:你使用字典self.ruleDictionary)来存储规则匹配时,规则iterate over its keysunmatched paranthesis循环。

字典在Python中没有保证的顺序。 Their order isn't arbitrary,但几乎无法预测,并且可能会在后续运行之间或甚至在修改字典之后发生变化。因此,在某些运行中,有问题的规则永远不会被测试,因为一个有效的正则表达式匹配,而break循环中的break匹配。

所以,你不能,也绝不应该依赖字典的特定顺序。那么你有什么选择呢?

1)使用有序的字典(Python 2.7 +)

您可以将for设为collections.OrderedDict的实例。 rulesDictionary将按照插入的顺序保留项目:

OrderedDict

2)按键对字典项进行动态排序,并迭代该有序序列:

from collections import OrderedDict
# ...
self.rulesDictionary = OrderedDict()

这将为您提供稳定的字母顺序,但不会为您插入项目的顺序。我相信这些规则的顺序与你的情况相关,所以你应该选择1)。