我需要的是使用python检查字符串是否是有效的数学表达式。
为简单起见,假设我只需要+ - * /
运算符(+ -
作为一元),数字和嵌套括号。我还为完整性添加了简单的变量名称。
所以我可以这样测试:
test("-3 * (2 + 1)") #valid
test("-3 * ") #NOT valid
test("v1 + v2") #valid
test("v2 - 2v") #NOT valid ("2v" not a valid variable name)
我尝试了pyparsing但只是尝试了这个示例:"simple algebraic expression parser, that performs +,-,*,/
and ^
arithmetic operations"我传递了无效代码并尝试修复它我总是得到错误的语法被解析而不会引发异常
只需尝试:
>>>test('9', 9)
9 qwerty = 9.0 ['9'] => ['9']
>>>test('9 qwerty', 9)
9 qwerty = 9.0 ['9'] => ['9']
两次测试通过...... o_O
有什么建议吗?
答案 0 :(得分:3)
这是因为pyparsing代码允许函数。(顺便说一下,它比你需要的更多,即创建一个堆栈并对其进行评估。)
对于初学者,您可以从代码中删除 pi
和ident
(可能还有我现在想念的其他内容)以禁用字符。
原因不同:默认情况下,PyParsing解析器不会尝试使用整个输入。您必须添加+ StringEnd()
(并将其导入(当然))到expr
的末尾,以使其无法解析整个输入时失败。在这种情况下,pyparsing.ParseException
将被提出。 (来源:http://pyparsing-public.wikispaces.com/FAQs)
如果你想学习一些解析,你需要的东西可以用不到三十行来构建任何像样的解析库(我喜欢LEPL)。
答案 1 :(得分:1)
为什么不评估它并捕获语法错误?
from math import *
def validateSyntax(expression):
functions = {'__builtins__': None}
variables = {'__builtins__': None}
functions = {'acos': acos,
'asin': asin,
'atan': atan,
'atan2': atan2,
'ceil': ceil,
'cos': cos,
'cosh': cosh,
'degrees': degrees,
'exp': exp,
'fabs':fabs,
'floor': floor,
'fmod': fmod,
'frexp': frexp,
'hypot': hypot,
'ldexp': ldexp,
'log': log,
'log10': log10,
'modf': modf,
'pow': pow,
'radians': radians,
'sin': sin,
'sinh': sinh,
'sqrt': sqrt,
'tan': tan,
'tanh': tanh}
variables = {'e': e, 'pi': pi}
try:
eval(expression, variables, functions)
except (SyntaxError, NameError, ZeroDivisionError):
return False
else:
return True
以下是一些示例:
> print validSyntax('a+b-1') # a, b are undefined, so a NameError arises.
> False
> print validSyntax('1 + 2')
> True
> print validSyntax('1 - 2')
> True
> print validSyntax('1 / 2')
> True
> print validSyntax('1 * 2')
> True
> print validSyntax('1 +/ 2')
> False
> print validSyntax('1 + (2')
> False
> print validSyntax('import os')
> False
> print validSyntax('print "asd"')
> False
> print validSyntax('import os; os.delete("~\test.txt")')
> False # And the file was not removed
它仅限于数学运算,因此 应该比原始eval
更好地工作。
答案 2 :(得分:1)
您可以尝试自己构建一个简单的解析器来标记算术表达式的字符串,然后构建表达式树,如果树有效(叶子都是操作数,内部节点都是运算符)那么你可以说表达式是有效的。
基本概念是创建一些辅助函数来创建解析器。
def extract()
将从表达式中获取下一个字符
def peek()
类似于提取,但如果没有空格来检查下一个字符,则使用
get_expression()
get_next_token()
或者,如果您可以保证字符之间有空格,则可以使用split()
进行所有标记化。
然后构建树并评估其结构是否正确
请尝试以获取更多信息:http://effbot.org/zone/simple-top-down-parsing.htm
答案 3 :(得分:1)
将parseAll=True
添加到parseString
的调用会将此解析器转换为验证器。
答案 4 :(得分:0)
如果您有兴趣修改用Python编写的自定义数学计算器引擎,以便它是一个验证器,那么您可以从Evaluator 2.0(Python 3.x)和Math_Evaluator开始(Python 2) 。X)。它们不是现成的解决方案,但允许您完全自定义您正在尝试使用(希望)易于阅读的Python代码。请注意“和”& “或”被视为经营者。