简体   繁体   English

数学表达式的正则表达式 Python

[英]Regular Expression for Mathematical Expression Python

I would like to come out with a regax which is able to match the mathematical expression which is being stored in exp .我想提出一个能够匹配存储在exp中的数学表达式的正则表达式。

The pattern of the expression starts and end with bracket and cannot contain any letters.表达式的模式以括号开头和结尾,不能包含任何字母。 The expression may contain integers or floats, and the operators can be +-*/** .表达式可以包含整数或浮点数,运算符可以是+-*/** Length of the expression is not limited.表达式的长度不受限制。

This is my regex:这是我的正则表达式:

import re
re.match(r'^[(]([(-]?([0-9]+)[)]??)([(]?([-+/*]([0-9]))?([.]?[0-9]+)?[)])[)]*$', exp)

However my regex doesn't match with some of the strings.但是我的正则表达式与某些字符串不匹配。 For example:例如:

  • exp = '(( 200 + (4 * 3.14)) / ( 2 ** 3 ))'
  • exp = '(23.23+23)'
  • exp = '((23**2)/23)'
  • exp = '(23.34-(3*2))'

I am new to regular expression and I am not sure which part of the expression is wrong, please forgive me for the trouble and hope that someone can help me with it.我是正则表达式的新手,我不确定表达式的哪一部分是错误的,请原谅我的麻烦,希望有人能帮助我。 Thank you so much!太感谢了!

You could approach it as "splitting" the string with operators being your separators.您可以将其视为“拆分”字符串,而运算符是您的分隔符。 This would save you from trying to represent numbers in your regular expression.这将使您免于尝试在正则表达式中表示数字。

So you only need an expression that will pick up the 5 operators and parentheses.因此,您只需要一个能够选择 5 个运算符和括号的表达式。 This can be expressed using a pipe between operators with the longest operator (**) being first.这可以在运算符之间使用 pipe 来表示,最长的运算符 (**) 位于首位。

import re
symbols   = ["**","+","-","*","/","(",")"]    # longest first
tokens    = re.compile("("+"|".join(map(re.escape,symbols))+")")
            # placing symbols in a group makes re.split keep the separators

def tokenize(exp):
  parts = map(str.strip,tokens.split(exp)) # split and strip spaces
  return list(filter(None,parts))          # remove empty parts

exp = '(( 200 + (4 * 3.14)) / ( 2 ** 3 ))'
print(tokenize(exp))
['(', '(', '200', '+', '(', '4', '*', '3.14', ')', ')', '/', '(', '2', '**', '3', ')', ')']


exp = '(23.23+23)'
print(tokenize(exp))
['(', '23.23', '+', '23', ')']

exp = '((23**2)/23)'
print(tokenize(exp))
['(', '(', '23', '**', '2', ')', '/', '23', ')']

exp = '(23.34-(3*2))'
print(tokenize(exp))
['(', '23.34', '-', '(', '3', '*', '2', ')', ')']        

Then you can perform a second pass and validate that the components are either an operator or a valid number as well as check that the expression is well formed with matching parentheses and alternating operator/operand.然后您可以执行第二遍并验证组件是运算符还是有效数字,并检查表达式是否具有匹配的括号和交替的运算符/操作数。 At that point you will know exactly what part of the expression is incorrect.到那时,您将确切地知道表达式的哪一部分是不正确的。

for example:例如:

def validate(exp):
    parts    = tokenize(exp)
    error    = ""
    pLevel   = 0
    previous = "$"
    for errorPos,part in enumerate(parts):
        pLevel += (part=="(")-(part==")")
        if pLevel<0: error="too many closing parentheses";break
        if part in "**+/)" and previous in "$**+-/(" :
            error = "missing operand";break 
        if part not in "**+-/)" and previous not in "$**+-/(":
            error = "missing operator";break
        previous = part
        if part in ["**","*","+","-","/","(",")"]: continue
        if all(p.isdigit() for p in part.split(".",1)): continue
        error = "invalid operand: " + part
        break
    if not error and pLevel!=0:
        errorPos,error = len(parts),"unbalanced parentheses"
    if not error and previous in "**+-/":
        errorPos,error = len(parts),"missing operand"
    if error:
        print("".join(parts))
        indent = " " * sum(map(len,parts[:errorPos]))
        print(indent+"^")
        print(indent+"|__ Error!",error)

... ...

validate('(( 200 + (4 * 3,14)) / ( 2 ** 3 ))')
                       
((200+(4*3,14))/(2**3))
         ^
         |__ Error! invalid operand: 3,14


validate('(( 200 + (4 * 3.14)) / ( 2 ** 3 )') 

((200+(4*3.14))/(2**3)
                      ^
                      |__ Error! unbalanced parentheses


validate('(( 200 + (4 * 3.14)))) / ( 2 ** 3 )') 

((200+(4*3.14))))/(2**3)
                ^
                |__ Error! too many closing parentheses


validate('(( 200 + *(4 * 3,14)) / ( 2 ** 3 ))')

((200+*(4*3,14))/(2**3))
      ^
      |__ Error! missing operand


validate('(( 200 + ()(4 * 3,14)) / ( 2 ** 3 ))')

((200+()(4*3,14))/(2**3))
       ^
       |__ Error! missing operand


validate('(( (200 + )(4 * 3,14)) / ( 2 ** 3 ))')

(((200+)(4*3,14))/(2**3))
       ^
       |__ Error! missing operand


validate('(( (200 + 2)(4 * 3,14)) / ( 2 ** 3 ))')

(((200+2)(4*3,14))/(2**3))
         ^
         |__ Error! missing operator

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM