javascript中嵌套括号的regex

regex for nested parenthesis in javascript

本文关键字:regex 嵌套 javascript      更新时间:2023-09-26

我正在用Javascript编写一个计算器。

我想把:[expression1]^[expression2]翻译成:Math.pow([expression1], [expression2])

当我有像5^-3这样的简单表达式时,使用正则表达式很容易,但当它有像这样的更复杂的表达式时

(-5*(6+3)-5)^((2*2)-2)+(4*5)

我不知道如何用regex处理它,因为嵌套的括号。。。

有什么建议吗?谢谢

使用正则表达式模式:

/((?:(?=[^()]*'d)'d*(?:'.'d*)?)|(?:'((?:(?:[^()]+)|(?:[^()]*'([^()]*')[^()]*)+)')))'^((?:(?=[^()]*'d)'-?'d*(?:'.'d*)?)|(?:'((?:(?:[^()]+)|(?:[^()]*'([^()]*')[^()]*)+)')))/

检查一下这把小提琴


解释:

[步骤1]:Regex模式包含两个几乎相同的子模式,在之间用^符号连接

((?:(?=[^()]*'d)'d*(?:'.'d*)?)|(?:'((?:(?:[^()]+)|(?:[^()]*'([^()]*')[^()]*)+)')))
'^
((?:(?=[^()]*'d)'-?'d*(?:'.'d*)?)|(?:'((?:(?:[^()]+)|(?:[^()]*'([^()]*')[^()]*)+)')))

唯一的区别是第二个(在^之后)允许负数作为简单参数('-?

[步骤2]::步骤1中的子模式有两个备选方案:

(?:(?=[^()]*'d)'-?'d*(?:'.'d*)?)
|
(?:'((?:(?:[^()]+)|(?:[^()]*'([^()]*')[^()]*)+)'))

[步骤3]::第一个选项是数字-例如:123412.341234..1234

(?=[^()]*'d)
'-?'d*
(?:'.'d*)?

[步骤4]::第二种选择是嵌套括号公式

'(
(?:(?:[^()]+)|(?:[^()]*'([^()]*')[^()]*)+)
')

[步骤5]::可能是简单的,也可能是复杂的(内有其他括号)

(?:[^()]+)
|
(?:[^()]*'([^()]*')[^()]*)+

[步骤6]::如果是复杂的,并且里面有其他括号,我们确保有嵌套的

[^()]*
'(
[^()]*
')
[^()]*

浏览器javascript,就像现在一样。不支持递归正则表达式。

我的解决方案是将前缀与正则表达式匹配。然后使用标记器方法搜索其括号。如果括号是平衡的,则返回括号内的块。

// replace_tokenizer_paranthesis by shimon doodkin
// this function is searching for a regexp prefix
// then searching for a chunk inside balanced parantheseis
//
// s="s( s(gdfgs)fasd)" - searched string
// prefix=/s'(/   - searched regex for prefix
// onmatch: - replace callback function, arguments:
//  a= prefix,
//  b= inside data,
//  c = closing paranthesis
//  to return same , return  [a,b+c]
//
// example:
// replace_tokenizer_paranthesis(s,prefix,function (a,b,c){ return [ "CONVERT(",b+",DATE)"  ] }) // return [ newprefix , all rest ]
function replace_tokenizer_paranthesis(s,prefix,onmatch) 
{
 var m,start=0;
 var input;
 while(m=(input=s.substr(start)).match(prefix))
 {
    var offset_at_end=m.index+m[0].length;

    var counter = 1;
    var skip_until="";
    var i = offset_at_end;
    for(; i < input.length; i++)
    {
        //var pc = i-1>=0?input[i-1]:"";
        var c = input[i];
        if( counter===0 )
        {
            break;
        }
        //else if(c===skip_until&& pc!=='''') //maybe backslash queoted
        else if(c===skip_until)
        {
            skip_until='';
        }
        else if(c==='"')
        {
            skip_until='"';
        }
        else if(c==="'")
        {
            skip_until="'";
        }
        else if(c==='(')
        {
            counter++;
        }
        else if(c===')')
        {
            counter--;
        }
    }
    if( counter===0 )
    {
            var result=onmatch(m[0], input.substring(offset_at_end,i-1),")")
            s=s.substring(0,start+m.index)+result[0]+result[1]+s.substr(start+i);
            start+=result[0].length;
    }
    else
      start+=offset_at_end;
 }
 return s
}