Regex не является правильным инструментом для задания. Просканируйте строку вручную.
Псевдокод:
depth = 0
for character in some_string:
depth += character == '('
depth -= character == ')'
if depth < 0:
break
if depth != 0:
print "unmatched parentheses"
Согласитесь с тем, что это невозможно с REGEX. Вы могли сделать следующее, хотя:
<?php
$testStrings = array( 'This is (ok)', 'This (is) (ok)', 'This is )bad(', 'This is also (bad', 'This is (bad (too)' );
foreach( $testStrings as $string ) {
$passed = hasMatchedParentheses( $string ) ? 'passed' : 'did not pass';
echo "The string $string $passed the check for matching parenthesis.\n";
}
function hasMatchedParentheses( $string ) {
$counter = 0;
$length = strlen( $string );
for( $i = 0; $i < $length; $i ++ ) {
$char = $string[ $i ];
if( $char == '(' ) {
$counter ++;
} elseif( $char == ')' ) {
$counter --;
}
if( $counter < 0 ) {
return false;
}
}
return $counter == 0;
}
?>
Вы можете делать это с регулярным выражением - PCRE, как используется PHP, позволять рекурсивные шаблоны. Руководство PHP дает пример , который является почти точно, что Вы хотите:
\(((?>[^()]+)|(?R))*\)
Это соответствует любой правильно заключенной в скобки подстроке, пока она начинается и заканчивается круглыми скобками. Если Вы хотите удостовериться, что вся строка сбалансирована, позволив строки как "wiggedy (wiggedy) (wiggedy (ненормальный))", вот то, что я придумал:
^((?:[^()]|\((?1)\))*+)$
Вот объяснение шаблона, который может больше освещать, чем путанный:
^ Beginning of the string ( Start the "balanced substring" group (to be called recursively) (?: Start the "minimal balanced substring" group [^()] Minimal balanced substring is either a non-paren character | or \((?1)\) a set of parens containing a balanced substring ) Finish the "minimal balanced substring" group * Our balanced substring is a maximal sequence of minimal balanced substrings + Don't backtrack once we've matched a maximal sequence ) Finish the "balanced substring" pattern $ End of the string
существует много соображений эффективности и правильности, которые придумывают эти виды regexes. Будьте осторожны.
Ваши примеры не включают, любой вложил parentheses†¦, если Вы не обеспокоены вложением, затем это может быть сделано с помощью следующего выражения:
^[^()]*(?:\([^()]*\)[^()]*)*$
Это будет соответствовать против всех строк в Вашем "позволять" список и сбой против строк в Вашем "предотвращать" список. Однако это также перестанет работать против любой строки с вложенными круглыми скобками . например, "это (не хорошо)"
, Поскольку другие уже указали, регулярные выражения не являются корректным инструментом, если необходимо обработать вложение.
Не возможно выполнить это с regex. Фигурная скобка, соответствующая, требует рекурсивной функции / функции подсчета, которая не доступна в regex. Вам будет нужен синтаксический анализатор для этого.
[еще 112] детали, доступные здесь: http://blogs.msdn.com/jaredpar/archive/2008/10/15/regular-expression-limitations.aspx
Для расширения ответа JaredPar не очень трудно решить, не используя regex, просто записать функцию, которая исследует каждый символ в строке и увеличивает/постепенно уменьшает счетчик. Если Вы находите" (", увеличивает это, и если Вы находите")", постепенно уменьшается это. Если счетчик когда-нибудь понижается 0, можно повредиться, строка недопустима. При обработке целой строки если счетчик не 0, была несопоставленная открывающая скобка.
, Почему это не возможно с regex
, другие ответы все корректны, но я просто хочу вставить разъем для теоретической информатики... это - случай, где знание теории дает фактическое практическое преимущество.
А regex соответствует детерминированному конечному автомату (DFA), но соответствие paren требует контекстно-свободной грамматики, которая может быть осознана как конечный автомат (КПК), но не DFA.
из-за этого, без большого количества дополнительной умственной деятельности, мы знаем, что ответ не, и мы не должны волноваться, что существует что-то, что мы просто пропускаем. Так, можно быть уверены в вышеупомянутых ответах и не волноваться, что авторы просто пропускают что-то, когда они дают тот ответ.
Почти все книги компилятора будут рассказывать об этом, вот быстрый обзор: