Как проверить, равно ли количество открытых фигурных скобок количеству близких фигурных скобок?

Как проверить, равно ли количество открытых фигурных скобок, количество закрытых фигурных скобок, используя регулярные выражения?

Вот код:

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");
}

Ответы

Ответ 1

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() приведет к синтаксической ошибке, если ваш код неверен. Улавливание ошибки означает, что вы можете справиться с этим безопасно и делать все, что захотите. Другое дело, что он не выполняет код, он просто разбирает его. В основном, вы используете свою задачу для анализатора браузера.

Он не использует регулярное выражение, но проверяет, действительно ли ваш код. Таким образом, он сообщает вам, соответствуют ли круглые скобки.

Ответ 2

Задача может быть просто решена без регулярного выражения, просто подсчитайте фигурные скобки.

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');

Ответ 3

Если ваша цель - проверить правильность выражения (это также означает, что подстрока, содержащая только скобки, формирует правильную последовательность скобок), то регулярные выражения вам не помогут.

Регулярные выражения могут обрабатывать так называемые " обычные языки" (хотя регулярные выражения JS могут быть несколько более мощными, чем их теоретические аналоги, цена таких мощность - большая сложность), а язык правильных последовательностей скобок не является регулярным.

Смотрите эти слайды - они могут дать вам представление о том, почему регулярные выражения не могут распознать правильную последовательность скобок.

Тем не менее, проблема не так сложна. Вы должны просто поддерживать стек и перебирать свою строку слева направо. Каждый раз, когда вы встречаете открывающий кронштейн, вы вставляете его в стек. Когда вы встретите закрывающую скобку, вы поместите верхний элемент стека и проверьте, соответствует ли его тип вашему (да, этот алгоритм может обрабатывать скобки нескольких типов). В конце вы должны просто проверить, пуст ли пуст.

Если вам не нужно обрабатывать разные типы скобок (например, у вас есть только "(" и "), вы можете просто сохранить переменную openBrackets (по существу, это будет представлять размер стека) и дон 'пусть он станет отрицательным.

Ответ 4

if (expression1.match(/\(/g).length === expression2.match(/\)/g).length) {
    // is equal
}

Чтобы заставить его работать со строками, не содержащими скобок, вы можете использовать следующее обходное решение:

((expression1.match(/\(/g) || []).length

Ответ 5

Вот еще один способ сделать это:

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;
}

Ответ 6

Если вы только заботитесь о count, почему бы вам не попробовать что-то вроде этого.

if(expression1.split('(').length == expression1.split(')').length) {
  alert('matched');
}

Ответ 7

  • "Мне нужно сопоставить число открытых фигурных скобок, равное отсутствию близких фигурных скобок, с использованием регулярного выражения"

  • "Мне нужно также проверить действительный синтаксис".

Если значение 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

Ответ 8

Попробуйте...

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

... тогда ваш код для предупреждений будет следующим:

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

Рабочая копия: jsFiddle

Ответ 9

Для нахождения числа скобок можно применить следующее. Однако он не использует 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();
}