正则表达式将算术表达式分成几部分

时间:2016-09-19 06:47:38

标签: javascript jquery regex

我正在创建一个计算器,我从输入字段中获取一个字符串。例如,该字符串可以是2+3*9/3-6

现在我想首先执行乘法和除法运算, 所以我会得到2+ 9 -6,其中9将是更高优先级操作的答案。

到目前为止,我已经这样做了。这是一个完整的功能:

function calculateResult(){
    var higher = /(\d+[*\/]\d+)/g;
    calstr = $('#input-display').val();
    var m = '*';
    var res = calstr.split(higher);
    console.log(res.length+ ' : ' + res);
    // console.log(res);
    if(res.length > 2){
        console.log('split success');
        var index = 0;
        do{
            for(var i = 1; i < res.length; i+=2){
                var a = res[i].split(/([0-9\.]+)/g);
                console.log('before calculation : '+calstr);
                var regex = RegExp('(?:.*?(\\d+[*\/]\\d+)){' + i + '}');
                console.log('regex generated : '+regex);
                if(a[2] == '*'){
                    calstr = calstr.replace(regex , Number(a[1])*Number(a[3]));
                }
                else if(a[2] == '/'){
                    calstr = calstr.replace(regex , Number(a[1])/Number(a[3]));
                }
                console.log('replaced result : ' + calstr);
                console.log('replaced result at : ' + calstr.search(regex));
            }
            // console.log('result : ' + calstr);
            console.log('multiplication complete');
            res = calstr.split(higher);
            console.log('result is : '+res);
        }while(res.length > 2);
    }
    else if(res.length == 1)
        console.log('split failed');
}

当我尝试替换字符串中的结果时,替换成功。但是在几个输入上它取代了作为参数传递给该函数的整个字符串,这不是我想要的。

我做错了什么?

如果仍然不清楚,我很乐意澄清。

乘法和除法运行平稳后,我计划更改这些正则表达式,以添加对加法和减法的支持。它将使用相同的代码,但下一次运行较低的优先级运算符。

3 个答案:

答案 0 :(得分:2)

仅仅评估输入会不会更简单?

&#13;
&#13;
function doEval() {
  try {
    alert(eval(document.querySelector('input').value));
  } catch (error) {
    alert('Invalid input: ' + error);
  }
}
&#13;
<input type='text' value='1+(4-3)*10/5' />
<input type='button' onclick='doEval();' value='Eval' />
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这个正则表达式是导致错误结果的原因:

RegExp('(?:.*?(\\d+[*\/]\\d+)){' + i + '}');

它不应与.*?匹配,因为这将使您删除后面的replace中的所有前面的字符。

此外,单\是不必要的。如果你真的想要转义正则表达式的/,你必须加倍前面的反斜杠,因为它也需要在引用的字符串中进行转义。但由于正斜杠不会出现在正则表达式文字中(如/.../g),因此根本不需要进行转义。

{' + i + '}部分没用。这只需要多次出现一个模式,但是在你已经进行了几次替换之后这可能是错误的。实际上,您需要每次匹配第一个匹配项,因为之前的所有匹配项都已被替换。

所以应该就是这样:

    RegExp('(\\d+[*/]\\d+)');

...所以它实际上与higher正则表达式没有区别,除了全局修饰符。但higher上的全局修饰符不是必需的,因为split无论如何都会搜索所有匹配项,即使没有该修饰符也是如此。这意味着您实际上只需要higher(没有g),而不是上面的正则表达式。

其他一些需要改进的地方:

  1. 以下调试行没什么用处,因为 calstr 已被修改,而正则表达式在修改之前应用了:

    console.log('replaced result at : ' + calstr.search(regex));
    
  2. 最好不要访问函数内的输入元素input-display。而是将calstr作为函数参数传递。这使它独立于您的浏览器上下文。

  3. 使用单一加号(Number(...))可以缩短
  4. +

  5. 这是更新的代码,它还实现了+-处理,将整个事物放在另一个循环中,该循环有3次迭代:一个用于*和{{1其他两个/(必须在-之前!)和+。这有另一个复杂性:单一的减号不应该与正常的减号运算符混淆。您将看到在内部正则表达式中使用+进行管理。

    (?:^-)?
    function calculateResult(calstr){
        for (var level = 0; level < 3; level++) {
            var search = level == 0 ? '(\\d+[*/]\\d+)'
                       : level == 1 ? '(-?\\d+-\\d+)'
                                    : '(-?\\d+\\+\\d+)';
            var higher = RegExp(search);
            var res = calstr.split(higher);
            while(res.length > 2){
                for(var i = 1; i < res.length; i+=2){
                    var a = res[i].split(/((?:^-)?[0-9\.]+)/g);
                    calstr = calstr.replace(higher, 
                         a[2] == '*' ? +a[1] * +a[3]
                       : a[2] == '/' ? +a[1] / +a[3]
                       : a[2] == '+' ? +a[1] + +a[3]
                                     : +a[1] - +a[3]
                    );
                }
                res = calstr.split(higher);
            }
        }
        return res[0];
    }
    
    $('button').click(function () {
       var input = $('#input-display').val();
       var result = calculateResult(input);
       $('span').text(result);
    });

    请注意,您正在重新发明轮子,因为JavaScript提供了<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input id="input-display" value="2+3*9/3-6"> <button>Calc</button><br> Result: <span></span>函数来评估(受控)表达式。此外,此代码不会评估更复杂的表达式,例如它们有括号时。

答案 2 :(得分:0)

好像你的第一个正则表达式var higher = /(\d+[*\/]\d+)/g;没有检索&#34; 3 * 9/3&#34;从2 + 3 * 9 / 3-6(在https://regex101.com/#javascript中查看)

尝试将其更改为

var higher = /(\d[^\+\-]*)+/g;