我的问题非常简单,假设我有一个像s = 'line $sin(2*x) $x*cos(x) $x'
这样的字符串,我知道其他地方的x
(例如1.0)的值。现在我想评估字符串,使它变成s = line 0.909 -0.416 1.0'
。你可以看到字符串s中有三个数学表达式:每个以$符号开头,以空格或行尾结束。
这个想法应该很简单:使用正则表达式和re.sub
函数。我之前对正则表达式一无所知,经过一两个小时我就知道了它的基本原理,但仍然无法弄清楚如何获得一个匹配三个表达式的正确模式,每个表达式都是独立的。如果我成功了,剩下的部分很简单,使用eval()计算表达式,转换为字符串,并汇编要返回的整个字符串。我想出的代码如下。
import re
from math import *
# parameters
x = 1.0
# test strings
s = 'line $sin(2*x) $x*cos(x) $x'
p = '\$[\s+]'
def replacer(s):
if s.startswith('$'):
return eval(s[1:])
else:
return "ERROR"
print re.sub(p,replacer,s)
我确信正则表达式是错误的,因为它没有捕获三种模式,我用不同的模式进行了多次实验......有人可以帮助我获得一个工作模式吗?然后我想我可以继续其余的事情了。 更新:问题已解决,请参阅下面的选定答案。
答案 0 :(得分:2)
您的第一个问题是您在正则表达式中使用[\s+]
,它只会与空格或+符号匹配一次。
你需要的正确表达式是\$(\S+)
,它将除$符号之外的所有内容放入捕获组中供以后使用。
其次,您需要以pythonic方式开始编写Python。使用您的值和表达式行将随机变量放在所有地方是不可重用的 相反,将重复变量封装在函数的范围内。从长远来看,这将不那么令人头痛。
此实例中所需的正则表达式函数不是re.sub
,而是re.findall
。此函数遍历字符串中的所有匹配项。
你会注意到我在使用之前编译了正则表达式,这只是在这个例子中允许更清晰的代码。
最后,我们遍历了一个非常简单的list()
数据类型的正则表达式匹配。
如您所见,您只需在任何表达式和任意值上调用evaluate_expression()
函数。
import re
from math import *
def evaluate_expression(equation, **kwargs):
for key in kwargs:
exec key + " = " + str(kwargs[key]) # Creates x variable
parser = re.compile(r'\$(\S+)')
expressions = parser.findall(equation)
for expression in expressions:
print eval(expression)
evaluate_expression('line $sin(2*x) $x*cos(x) $x', x=1.0)