使用正则表达式处理数学方程中的嵌套括号?

时间:2012-04-19 23:48:58

标签: python regex

如果我有:

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

我希望能够为我正在编写的数学读者在括号内处理多个括号。也许我会以错误的方式解决这个问题,但我的目标是递归地深入括号,直到没有,然后我会执行数学运算。因此,我首先要关注

"(2*(3+1))" 

然后专注于

"(3+1)"

我希望通过将焦点值分配给正则表达式的起始索引和正则表达式的结束索引来实现此目的。我还没弄清楚如何找到结束索引,但我更感兴趣的是首先匹配正则表达式

r"\(.+\)" 

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

3 个答案:

答案 0 :(得分:12)

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

不要使用正则表达式。

你想要一个真正解析你的数学表达式的实际解析器。你可能想读这个:

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

一旦你实际解析了表达式,走遍解析树并计算结果是微不足道的。

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

http://pyparsing.wikispaces.com

以下是四函数代数表达式求值程序的pyparsing示例代码的直接链接:

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

答案 1 :(得分:2)

对于它的价值,这里有更多的背景:

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

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

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

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

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

  3. 你已经完成了!这场比赛很成功!

  4. 这是一个“确定性有限自动机”。

    无论如何,这个有趣的部分是,如果你坐下来尝试做出类似的东西来匹配一对括号,你就不能!试试吧。您可以通过制定越来越多的规则来匹配有限数字,但是您不能编写与无限数量的括号匹配的一般规则集(我应该添加规则必须是“如果您匹配X的规则”到Y“)。

    现在显然你可以用各种方式修改它。你可以允许更复杂的规则(比如扩展它们以让你保持括号的数量),然后你可以得到一些像你期望的那样工作的东西。但它不是常规语法。

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

    最终的免责声明和承诺的额外细节:在实践中,现在许多正则表达式实际上 比这更强大(并且不应该被称为“正则表达式”)。但上面仍然是为什么你不应该使用正则表达式的基本解释。

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

答案 2 :(得分:1)

我可能同意steveha,并且不建议使用正则表达式,但要具体回答你的问题,你需要未转义的parens来取出结果组(你的模式只有逃脱的parens):

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

如果你走这条路线,你可以迭代匹配结果,直到你的比赛用完为止,然后反转结果列表以完成内部工作。