Python re.match中的不平衡圆括号



使用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是一个字典,其中productions是映射到相关tokenName的密钥,rulesruleDictionary的密钥列表,item是读取的字符串。由于一些结果很容易用正则表达式求和,例如[a-z]+d+,因此字典键可以是正则表达式定义,这就是这个循环的目的。

问题:

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

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

所以你需要用()逃离它们。你可以用

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

如果你想了解更多,不平衡括号python这个问题还有其他信息。

正如@Kuhess的回答中所描述的,您面临的直接问题是,您的规则包含了偏旁性,并将其用作正则表达式,但无法逃脱偏旁性(或*等正则表达式中具有特殊含义的其他字符)。

然而,这仍然不能解释您观察到的行为,即在尝试匹配规则之前添加print()调用似乎可以解决问题。

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

因此,我仔细查看了您的代码,我确信我知道您的代码不具有确定性的原因:您使用字典self.ruleDictionary)来存储规则,迭代其键,并在规则匹配时立即循环break

字典在Python中没有保证的顺序。它们的顺序不是任意的,但几乎不可能预测,并且可能在后续运行之间发生变化,甚至在修改字典之后发生变化。因此,在某些运行中,有问题的规则永远不会得到测试,因为一个有效的正则表达式匹配,并且您将breakfor循环中排除。

因此,你不能也永远不应该依赖字典的特定顺序。那么你有什么选择呢?

1)使用有序dict(Python 2.7+)

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

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

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

for key, value in sorted(dct.items(), key=lambda x: x[0]):
    # ...

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

最新更新