21

如何使用正则表达式检查左大括号的数量是否等于右大括号的数量?

这是代码:

var expression1 = "count(machineId)+count(toolId)";
var expression2 = "count(machineId)+count(toolId))";

这些是 2 个表达式,其中在 中expression1,开括号的数量等于闭括号expression2的数量,在 中,开括号的数量不等于闭括号的数量。我需要一个正则表达式来计算左括号和右括号的数量并给我警报。我也需要检查有效的语法。

if(expression1.......){ // here goes the regular expression
    alert("Matched");
}
else{
    alert("Not matched");
}
4

9 回答 9

61
var expression1 = "count(machineId)+count(toolId)";
var expression2 = "count(machineId)+count(toolId))";

if (matches(expression1)) {
    alert("Matched"); // Triggered!
}
else {
    alert("Not matched");
}

if (matches(expression2)) {
    alert("Matched");
}
else {
    alert("Not matched"); // Triggered!
}

function matches(str) {
    try {
        new Function(str);
        return true;
    }
    catch (e) {
        return !(e instanceof SyntaxError);
    }
}

这是有效的,因为new Function()如果您的代码错误,将导致语法错误。捕获错误意味着您可以安全地处理它并做任何您想做的事情。另一个好处是它不执行代码,它只是解析它。基本上,您将任务用于浏览器的解析器。

它不使用正则表达式,但会检查您的代码是否有效。因此,它会告诉您括号是否匹配。

于 2012-12-19T11:06:45.807 回答
13

无需正则表达式即可轻松解决任务,只需计算大括号即可。

var a = 'count(machineId)+count())toolId)'
var braces = 0;
for (var i=0, len=a.length; i<len; ++i) {
   switch(a[i]) {
       case '(' : 
          ++braces;
          break;
       case ')' : 
           --braces;
           break;
   }
   if (braces < 0) {    
      alert('error');
      break;
   }
}

if (braces)
    alert('error');
于 2012-12-19T11:00:30.817 回答
5

如果您的目标是检查表达式是否有效(这也意味着它的仅包含括号的子字符串形成正确的括号序列),那么正则表达式对您没有帮助。

正则表达式只能处理所谓的“正则语言”(尽管 JS 正则表达式可能比它们的理论对应物更强大,但这种能力的代价是更大的复杂性),而正确括号序列的语言不是正则的。

查看这些幻灯片——它们可以让您了解为什么正则表达式无法识别正确的括号序列。

尽管如此,问题并不难。您应该只维护一个堆栈并从左到右遍历您的字符串。每次遇到开口支架时,您都会将其推入堆栈。当您遇到右括号时,您弹出堆栈的顶部元素并检查其类型是否与您的类型匹配(是的,该算法可以处理多种类型的括号)。最后,您应该检查堆栈是否为空。

如果您不需要处理不同类型的括号(例如,您只有“(”和“)”),您可以只维护一个变量openBrackets(本质上它代表堆栈的大小)并且不要让它变成负数.

于 2012-12-19T11:31:33.767 回答
4
if (expression1.match(/\(/g).length === expression2.match(/\)/g).length) {
    // is equal
}

为了使其与不包含大括号的字符串一起使用,您可以使用以下解决方法:

((expression1.match(/\(/g) || []).length
于 2012-12-19T10:53:32.130 回答
3

如果您只关心计数,为什么不尝试这样的事情。

if(expression1.split('(').length == expression1.split(')').length) {
  alert('matched');
}
于 2012-12-19T11:00:14.623 回答
3

这是另一种方法:

function validParenNesting(text) {
    var re = /\([^()]*\)/g; // Match innermost matching pair.
    // Strip out matching pairs from the inside out.
    while (text.match(re))
        text = text.replace(re, '');
    // If there are any parens left then no good
    if (text.match(/[()]/))
        return false;
    // Otherwise all parens part of matching pair.
    return true;
}
于 2012-12-19T16:17:11.190 回答
0
  1. “我需要使用正则表达式匹配开括号的数量等于闭括号的数量”

  2. “我也需要检查有效的语法。”

如果2为真,那么1也为真。因此,查找您所知道的有效语法的匹配项——在这种情况下:{}. 执行一个循环,从“堆栈”中删除所有有效匹配,直到没有有效匹配。如果最后剩下的什么都没有,那么这意味着你的论点是 100% 有效的。如果最后剩下的是什么——这意味着“剩余”没有通过你的有效性测试,因此是无效的:

var foo = function(str) {
    while(str.match(/{}/g))           // loop while matches of "{}" are found
        str = str.replace(/{}/g, ''); // "slices" matches out of the "stack"
    return !str.match(/({|})/g);      // `false` if invalids remain, otherwise `true`
};

foo('{{{}}}'); // true
foo('{{}}}}}}}}}}{}'); // false
于 2013-03-14T21:14:05.677 回答
0

尝试 ...

function matchBraces(s) {
  return s.match(/\(/g).length === s.match(/\)/g).length;
}

...那么,您的警报代码如下...

if(matchBraces(expression1)) {
    alert("Matched");
} else {
   alert("Not matched");
}

工作副本:jsFiddle

于 2014-12-17T05:11:56.480 回答
0

以下可用于查找括号的数量。但是,它不使用 RegExp 并且使用简单的逻辑。

var l = 0;
var r = 0;
//Count the number of brackets.
for(var i=0;i<str.length;i++){
  if(str[i]=="("){
    l++;
  }
  else if(str[i]==")"){
    r++;
  }
}
if(l==r){ //The number of opening and closing brackets are equal.
  doSomething();
}
于 2017-06-12T10:34:45.320 回答