For a solution without using eval, here is what I will do. Start by looking for all the mathematical expressions in the string, which I will define as a string containing spaces, brackets, numbers and operations, and then cross out the matches, all spaces:
>>> import re >>> my_str = 'I have 6 * (2 + 3) apples' >>> exprs = list(re.finditer(r"[\d\.\s\*\+\-\/\(\)]+", my_str)) >>> exprs = [e for e in exprs if len(my_str[e.start():e.end()].strip()) > 0]
Then evaluate the expressions using the NumericStringParser class from this question , which uses pyparsing :
>>> nsp = NumericStringParser() >>> results = [nsp.eval(my_str[e.start():e.end()]) for e in exprs] >>> results [30.0]
Then, to substitute the results back into the expression, reverse the sorting of the expressions by their starting index and put them back in the original line:
>>> new_str = my_str >>> for expr, res in sorted(zip(exprs, results), key=lambda t: t[0].start(), reverse=True): ... new_str = new_str[:expr.start()] + (" %d " % res) + new_str[expr.end():] ... >>> new_str 'I have 30 apples'
jterrace
source share