使用正则表达式解析算术字符串

时间:2016-10-02 19:02:18

标签: python regex math

我需要解析只有*)和添加+)的算术字符串,例如{{1} },使用正则表达式。

我的工作代码如下:

300+10*51+20+2*21

我想知道是否有办法避免在上面创建变量import re input_str = '300+10*51+20+2*21' #input_str = '1*2+3*4' prod_re = re.compile(r"(\d+)\*(\d+)") sum_re = re.compile(r"(\d+)\+?") result = 0 index = 0 while (index <= len(input_str)-1): #----- prod_match = prod_re.match(input_str, index) if prod_match: # print 'find prod', prod_match.groups() result += int(prod_match.group(1))*int(prod_match.group(2)) index += len(prod_match.group(0))+1 continue #----- sum_match = sum_re.match(input_str, index) if sum_match: # print 'find sum', sum_match.groups() result += int(sum_match.group(1)) index += len(sum_match.group(0)) continue #----- if (not prod_match) and (not sum_match): print 'None match, check input string' break print result

2 个答案:

答案 0 :(得分:1)

算法似乎不正确。输入1*2+3*4不会产生正确的结果。在解决一个乘法后你继续解决一个加法似乎是错误的,而在某些情况下,你必须先做更多的乘法才能进行任何加法。

通过对正则表达式和循环进行一些更改,您可以按照以下方式实现所需:

import re

input_str = '3+1*2+3*4'

# match terms, which may include multiplications
sum_re = re.compile(r"(\d+(?:\*\d+)*)(?:\+|$)")
# match factors, which can only be numbers 
prod_re = re.compile(r"\d+")

result = 0
# find terms
for sum_match in sum_re.findall(input_str):
    # for each term, determine its value by applying the multiplications
    product = 1
    for prod_match in prod_re.findall(sum_match):
        product *= int(prod_match)
    # add the term's value to the result
    result += product

print (result)

解释

这个正则表达式:

(\d+(?:\*\d+)*)(?:\+|$)

...匹配一个整数,后跟零次或多次乘法:

(?:\*\d+)*

(?:使其成为非捕获组。如果没有?:,方法findall会将匹配的这一部分分配给我们不想要的单独的列表元素。

\*\d+是:一个字面的星号后跟数字。

最终(?:\+|$)也是一个非捕获组,需要跟随文字+或输入结束($)。

答案 1 :(得分:0)

问题的解决方案应该是term之后的可能符号,后跟一个术语列表,由添加运算符分隔,如

[+-]?({term}([+-]{term})*)

其中每个术语是一个因子,后跟可能的乘法运算符的空列表和另一个因子,如下所示:

{factor}([*/]{factor})*

其中因子是数字序列[0-9]+,所以替换,导致:

[+-]?([0-9]+([*/][0-9]+)*([+-][0-9]+([*/][0-9]+)*)*)

这将是一个可能的正则表达式,它假定您可以拥有的运算符之间的优先级结构。但是它不允许你提取不同的元素,正如很容易证明的那样:正则表达式里面只有4个组元素(左括号4)所以你只能匹配其中的四个(第一个术语,最后一个因子)第一个术语,最后一个术语,以及最后一个术语的最后一个因子。如果你开始用括号括起子表达式,你可以得到更多,但正则表达式中的组数是有限的事情,你可以构造一个可能无限长的正则表达式。

这说(你将无法将所有事物组与正则表达式结构分开)采用不同的方法:第一个符号是可选的,后面可以跟一个未定义的术语数,由乘法运算符分隔或添加的:

[+-]?([0-9]+([*/+-][0-9]+)*

也可以完成这项工作(它与同一组表达式匹配。即使你限制了只有一个运算符可以在1位或更多位数的任何序列中间隔的事实,所得到的正则表达式可以简化为:

[-+]?[0-9]([*/+-]?[0-9])*

或使用现今使用的常用符号:

[-+]?\d([*/+-]?\d)*