使用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
的密钥,rules
是ruleDictionary
的密钥列表,item
是读取的字符串。由于一些结果很容易用正则表达式求和,例如[a-z]+
或d+
,因此字典键可以是正则表达式定义,这就是这个循环的目的。
问题:
目前,在运行我创建的示例定义文件和示例输入时,我遇到了一个unbalanced parenthesis
错误。但是,当我在if
语句之前取消对print()
语句的注释时,它工作得非常好。出于调试目的,我创建了print()
语句,但没有意识到它会对程序的实际执行产生影响。我完全迷路了,不知道为什么在启用打印时它能工作。
您的问题来自模式变量rule
的内容。它必须包含一个括号。但是在正则表达式中,括号有一个特殊的含义(组)。
所以你需要用(
或)
逃离它们。你可以用
rule.replace('(', '(')
rule.replace(')', ')')
如果你想了解更多,不平衡括号python这个问题还有其他信息。
正如@Kuhess的回答中所描述的,您面临的直接问题是,您的规则包含了偏旁性,并将其用作正则表达式,但无法逃脱偏旁性(或*
等正则表达式中具有特殊含义的其他字符)。
然而,这仍然不能解释您观察到的行为,即在尝试匹配规则之前添加print()
调用似乎可以解决问题。
我能够从您的回购中用unmatched
分支重现unmatched paranthesis
错误。然后,在不改变任何事情的情况下,使用完全相同的参数进行第二次运行!
因此,我仔细查看了您的代码,我确信我知道您的代码不具有确定性的原因:您使用字典(self.ruleDictionary
)来存储规则,迭代其键,并在规则匹配时立即循环break
。
字典在Python中没有保证的顺序。它们的顺序不是任意的,但几乎不可能预测,并且可能在后续运行之间发生变化,甚至在修改字典之后发生变化。因此,在某些运行中,有问题的规则永远不会得到测试,因为一个有效的正则表达式匹配,并且您将break
从for
循环中排除。
因此,你不能也永远不应该依赖字典的特定顺序。那么你有什么选择呢?
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)。