2017-02-22 46 views
1

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

Хорошие строки (должны быть согласованы):

aaaaaa 
(asdasd) 
aaaa(bbb)a 
(aaa)aaaa 
aaaaaa(aaaa) 
aaaa(bbb)(ccc)ddd 
aaaa(bbbb)cccc(dddd)eeee 

Плохие строки (там не должно быть матч):

)aaaa 
)aaaa(asd) 
aaaaaa(
aaaa(bbb)) 
aaa(bbb 
aaaaa((bbbb)cccc 
aaaa(bbbb))ccc 
aaaa(aasd(adssad))ad 
adassd(aas(add)adsa(asda)ad) 
() 

Пробовал и создал что-то вроде этого (?!.*[(]{2,})(?!.*[)]{2,})(?![)])(?!.*[(]$).*$, но все равно это не хорошо. Любая помощь в этом?

+1

Сколько уровней там может быть? Это хорошая строка или плохой: 'aaa (bb (cc) bb)'? –

+0

Один уровень круглых скобок является достижимым и практичным. Фиксированное количество уровней доступно, но не практично с более чем несколькими уровнями. Произвольное гнездование уже не является обычным языком. – 9000

ответ

3

Вы можете использовать это регулярное выражение для работы:

/^(?!$)(?:[^)(]*\([^()]+\))*[^)(]*$/gm 

RegEx Demo

RegEx Распад:

  • ^ - Линия запуска
  • (?!$) - Отрицательное опережение, чтобы убедиться, мы не сопоставляем пустую строку ING
  • (?: - начало, не захватывая группы
    • [^)(]* - Матч 0 или больше ничего, но ( и )
    • \( - Матч (
    • [^()]+ - Матч 1 или больше ничего, но ( и )
    • \) - Соответствие буквально )
  • )* - Конец не-захвата группы, * делает матч 0 или несколько раз
  • [^)(]* - Матч 0 или больше ничего, но ( и )
  • $ - линия конец
+0

Необязательно свернутый и многословный, не нужно сопоставлять '[^) (]' дважды. – georg

+0

@georg: он может выглядеть долговечным, но он будет более эффективным, чем '^ ([^()] | \ ([^()]) + \)) + $ '(вы можете проверить # шагов, предпринятых в regex101) – anubhava

2

Если вы хотите проверить сбалансированный паренс, вы можете использовать такую ​​функцию:

function balanced(str) { 
 
    var a = 0; 
 
    for(var i = 0; i < str.length; i++) { // for each character in str 
 
    if(str.charAt(i) == '(') a++;  // if it's an open paren, increment a 
 
    else if(str.charAt(i) == ')') a--; // if it's a close one, decrement a 
 
    } 
 
    return a == 0;       // if a == 0 then it's balanced (true), if not then it's not balanced (false) 
 
} 
 

 
var s1 = "aaaa(bbbb)cccc(dddd)eeee"; 
 
var s2 = "aaaa(bbbb(cccc(dddd)eeee"; 
 
var s3 = "aaaa"; 
 

 
console.log(s1 + " => " + balanced(s1)); 
 
console.log(s2 + " => " + balanced(s2)); 
 
console.log(s3 + " => " + balanced(s3));

Или, если вы настаиваете на использовании регулярных выражений, а затем использовать два регулярных выражений для проверки сбалансированных скобок, как это:

function balanced(str) { 
 
    var opened = str.match(/\(/g);  // match open parens 
 
    var closed = str.match(/\)/g);  // match close parens 
 
    opened = opened? opened.length: 0; // get the count of opened parens, if nothing is matched then 0 
 
    closed = closed? closed.length: 0; // get the count of closed parens, if nothing is matched then 0 
 
    return opened == closed;   // balanced means the count of both is equal 
 
} 
 

 
var s1 = "aaaa(bbbb)cccc(dddd)eeee"; 
 
var s2 = "aaaa(bbbb(cccc(dddd)eeee"; 
 
var s3 = "aaaa"; 
 

 
console.log(s1 + " => " + balanced(s1)); 
 
console.log(s2 + " => " + balanced(s2)); 
 
console.log(s3 + " => " + balanced(s3));

+1

Возможно, вы захотите проверить свою функцию с помощью' "))) x ((" '' – georg

0

Это должно сделать трюк:

^([^()]|\([^()]+\))+$ 

читает "matc h не paren или (no parens here), один или несколько раз, целая строка "

Если вы хотите совместить сбалансированные parens на любом уровне, одно из выражений невозможно в js из-за отсутствия поддержки рекурсии, но функция будет довольно тривиальной.

let balanced = function(s) { 
 
    var re = /\([^()]*\)/g 
 
    while (s.match(re)) s = s.replace(re, '') 
 
    return !s.match(/[()]/) 
 
} 
 

 
console.log(balanced('a(b((d))e) (f) g')) 
 
console.log(balanced('a(b((d))e? (f) g'))

или без регулярных выражений:

let balanced = s => { 
 

 
    let c = 0; 
 

 
    for (let x of s) { 
 
     if (x == '(') c++; 
 
     if (x == ')' && !c--) return false; 
 
    } 
 

 
    return !c; 
 
};

 Смежные вопросы

  • Нет связанных вопросов^_^