Javascript a^b而不是pow(a,b)的正则表达式
这是一个有趣的例子。有没有人有一个好的正则表达式可以将所有(第一个)^(第二个)转换为Math.pow((第一个),(第二个)) 编辑: 到目前为止,我所拥有的最好的是Javascript a^b而不是pow(a,b)的正则表达式,javascript,regex,Javascript,Regex,这是一个有趣的例子。有没有人有一个好的正则表达式可以将所有(第一个)^(第二个)转换为Math.pow((第一个),(第二个)) 编辑: 到目前为止,我所拥有的最好的是 s = s.replace(/((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))\s*\^\s*((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))/g, 'Math.pow($1, $2)') // r
s = s.replace(/((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))\s*\^\s*((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))/g, 'Math.pow($1, $2)') // replace expression ^ expression with Math.pow($1, $2)
到目前为止,答案还不够笼统。它们不包括(var1+var2)^2之类的内容,更不用说(var1*(var2+var3))^2了
解决方案必须使用括号
您可以使用strfriend.com帮助可视化您创建的正则表达式。这就是我一直在做的。您可以使用
字符串。替换:
> s = "hello 2^3 pow!"
> s.replace(/(\d+)\^(\d+)/, "Math.pow($1, $2)")
"hello Math.pow(2, 3) pow!"
这不能用正则表达式实现(至少不需要很多努力)。你必须考虑不同的括号,不能用一个简单的正则表达式来处理。我建议寻找一个能够解析数学表达式的库。或者,您必须将可能的表达式限制为可以使用简单正则表达式处理的内容
可以在正则表达式中定义命名和平衡捕获组,该正则表达式可以在同一正则表达式中使用(反向引用)。这样,您就必须定义所需的数学语法子集以及参数的两个捕获。我建议您不要重新发明轮子,而使用JS库
假设您想要转换源文件或类似的东西,请在源文件上运行一个perl脚本并使用。从大纲中:
use Math::Expression::Evaluator::Parser;
my $exp = '2 + a * 4';
my $ast = Math::Expression::Evaluator::Parser::parse($exp, {});
# $ast is now something like this:
# $ast = ['+',
# 2,
# ['*',
# ['$', 'a'],
# 4
# ]
# ];
看起来它可以轻松处理指数运算。因此,在您的案例中,AST将类似于:
# $ast = ['^',
# base,
# exp
# ];
您可以通过(递归地)重新组合来自“base”和“exp”子树的字符串来构建所需的表达式“Math.pow(base,exp)”
如果您想在JavaScript中实现计算器,那么您当然需要一个计算器,或者您可以依赖使用Math::Expression::Evaluator实现的服务器后端。坏消息是:正则表达式无法解决它(正如许多答案所示),您需要为此编写一个解析器
好消息是:通过编写递归下降解析器,您可以相对轻松地在几乎任何语言中实现这一点。当然,您应该尽可能多地重用现有代码,但是您自己编写递归下降解析器(并了解如何编码优先规则)纯粹是为了获得启发性的体验
拿起任何一本关于编译器构造的书,阅读关于解析的前几章。让我推荐Niklaus Wirth的4.1“递归下降的方法”。看看Jison,一个Javascript解析器生成器
特别是,查看他们的
console.log(caretReplace(“(3*(f(x^2)-2)^2+1^5-g(2^3+1)^5)^(9-2^3)”)代码>
给出Math.pow((3*Math.pow((f(Math.pow(x,2))-2),2)+Math.pow(1,5)-Math.pow(g(Math.pow(2,3)+1,5)),(9-Math.pow(2,3))
您的数学表达式必须是有效的,具有平衡的开括号和闭括号
您可以用所需的任何函数名替换Math.pow
我用非数学文本替换了所有括号,从最里面到最外面(\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu0
,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 1
,等等)。最后,我按层次分析所有这些字符串,以替换非括号表达式上的插入符号
你现在最接近的是…?a*b^c
应该转换成什么<代码>a^b+c
<代码>a^b^c
?这不能用普通正则表达式完成。它需要任意递归。如果你想要一个答案,我建议你提高悬赏,这是一个相当复杂的问题。你需要的是一个词法表达式解析器…已经有一段时间了,但我相信匹配任意括号/引号/聊天符通常不属于常规语言,因此不能被常规表达式解析;如果你有一种像parens这样的嵌套结构的语言,那么一种常规语言就不会切割它——事实上,它存在于“常规语言”的定义中。最好开始编写解析器,或者从众多解析器中找到一个。是死的,你能更新吗?这或者一个讨论在JS中实现类似功能的答案是正确的。如果你匹配模式中的可选括号,你可以通过删除多余的括号来增强它。
var caretReplace = function(_s) {
if (_s.indexOf("^") > -1) {
var tab = [];
var powfunc="Math.pow";
var joker = "___joker___";
while (_s.indexOf("(") > -1) {
_s = _s.replace(/(\([^\(\)]*\))/g, function(m, t) {
tab.push(t);
return (joker + (tab.length - 1));
});
}
tab.push(_s);
_s = joker + (tab.length - 1);
while (_s.indexOf(joker) > -1) {
_s = _s.replace(new RegExp(joker + "(\\d+)", "g"), function(m, d) {
return tab[d].replace(/(\w*)\^(\w*)/g, powfunc+"($1,$2)");
});
}
}
return _s;
};