6

如果我有:

statement = "(2*(3+1))*2"

我希望能够为我正在编写的数学阅读器处理括号内的多个括号。也许我的做法是错误的,但我的目标是递归地深入括号直到没有括号,然后我将执行数学运算。因此,我首先要关注

"(2*(3+1))" 

然后专注于

"(3+1)"

我希望通过将焦点值分配给正则表达式的开始索引和正则表达式的结束索引来做到这一点。我还没有弄清楚如何找到结束索引,但我对首先匹配正则表达式更感兴趣

r"\(.+\)" 

匹配失败。我希望它读作“一组括号中包含的任何一个或多个字符”。有人可以解释为什么上面的表达式与 python 中的上面的语句不匹配吗?

4

3 回答 3

13

我喜欢正则表达式。我一直在使用它们。

不要为此使用正则表达式。

您需要一个真正解析您的数学表达式的实际解析器。您可能想阅读以下内容:

http://effbot.org/zone/simple-top-down-parsing.htm

一旦你真正解析了表达式,遍历解析树并计算结果就很简单了。

编辑:@Lattyware 建议使用 pyparsing,这也应该是一个好方法,并且可能比上面发布的 EFFBot 解决方案更容易。

https://github.com/pyparsing/pyparsing

这是四函数代数表达式求值器的 pyparsing 示例代码的直接链接:

http://pyparsing.wikispaces.com/file/view/fourFn.py

于 2012-04-19T23:52:16.850 回答
2

对于它的价值,这里有更多的上下文:

正则表达式被称为“正则”,因为它们与正则语法相关联,而正则语法不能描述(无限数量的)嵌套括号(它们可以描述一堆随机括号,但不能使它们成对匹配)。

理解这一点的一种方法是理解正则表达式可以(模数我将在最后解释的一些细节)转换为确定性有限自动机。这听起来令人生畏,但实际上只是意味着它们可以转换为“规则”列表,其中规则取决于您匹配的内容,并描述您可以匹配的内容。

例如,正则表达式ab*c可以转换为:

  1. 一开始,您只能匹配a. 然后转到 2。

  2. 现在,您可以匹配b并返回 2,或者匹配c并返回 3

  3. 你完成了!比赛很成功!

那是一个“确定性有限自动机”。

无论如何,有趣的部分是,如果你坐下来尝试做类似的东西来匹配一对括号,你就做不到!尝试一下。你可以通过制定越来越多的规则来匹配一个有限的数字,但是你不能编写一套匹配无限数量的括号的通用规则(我应该补充一点,规则必须是“如果你匹配 X go玩具”)。

现在显然您可以通过各种方式对其进行修改。您可以允许更复杂的规则(例如扩展它们以让您保留括号的数量),然后您可以获得按预期工作的东西。但它不会是常规语法。

鉴于正则表达式以这种方式受到限制,为什么要使用它们而不是更复杂的东西?事实证明,它们是一个甜蜜点——它们可以做很多事情,同时保持相当简单和高效。更复杂的语法(规则种类)可能更强大,但也更难实现,效率问题也更多。

最后的免责声明和承诺的额外细节:实际上,如今许多正则表达式实际上这更强大(并且不应该真正称为“正则表达式”)。但以上仍然是为什么你不应该为此使用正则表达式的基本解释。

ps jesse 建议的解决方案通过多次使用正则表达式来解决这个问题;这里的论点是针对正则表达式的一次使用。

于 2012-04-20T00:34:24.697 回答
0

我可能同意 steveha,并且不建议为此使用正则表达式,但要具体回答您的问题,您需要未转义的括号来提取结果组(您的模式只有转义的括号):

>>> re.match(r"\((.+)\)", "(2*(3+1))*2").group(1)
'2*(3+1)'

如果你走那条路,你可以迭代匹配结果,直到你用完匹配项,然后反转结果列表以从里到外工作。

于 2012-04-20T00:29:22.817 回答