- This is (ok)
- This (is) (ok)
我想要防止的内容:
- This is )bad(
- This is also (bad
- This is (bad (too)
谢谢!
更新:你们都很棒。尝试使用正则表达式解决这个问题似乎比应该的更棘手,这些第二层次的答案是使stackoverflow美丽的原因之一。感谢提供链接和伪代码。我不确定该把答案给谁,所以我向那些我无法接受答案的人道歉。
我想要防止的内容:
谢谢!
更新:你们都很棒。尝试使用正则表达式解决这个问题似乎比应该的更棘手,这些第二层次的答案是使stackoverflow美丽的原因之一。感谢提供链接和伪代码。我不确定该把答案给谁,所以我向那些我无法接受答案的人道歉。
正则表达式不是解决这个问题的正确工具。手动扫描字符串。
伪代码:
depth = 0
for character in some_string:
depth += character == '('
depth -= character == ')'
if depth < 0:
break
if depth != 0:
print "unmatched parentheses"
您可以使用正则表达式进行此操作 - PHP使用的PCRE允许递归模式。PHP手册提供了一个示例,几乎与您想要的一样:
\(((?>[^()]+)|(?R))*\)
这个正则表达式匹配任何以圆括号开始和结束的正确括号子字符串。如果您想确保整个字符串是平衡的,并允许像“wiggedy(wiggedy)(wiggedy(wack))”这样的字符串,这就是我想出的:
^((?:[^()]|\((?1)\))*+)$
下面是一个比较易懂的正则表达式模式解释:
^ 字符串开头 ( 开始"平衡子字符串"组(将被递归调用) (?: 开始“最小平衡子字符串”组 [^()] 最小平衡子字符串是非括号字符 | 或者 \((?1)\) 包含一个平衡子字符串的一组括号 ) 结束“最小平衡子字符串”组 * 我们的平衡子字符串是最小平衡子字符串的最大序列 + 一旦我们匹配到最大序列就不回溯 ) 结束“平衡子字符串”模式 $ 字符串结尾
这类正则表达式涉及的效率和正确性方面需要注意。
使用正则表达式无法完成这个任务。括号匹配需要一种在正则表达式中不可用的递归/计数功能。你需要使用解析器来实现。
更多详情请参见:http://blogs.msdn.com/jaredpar/archive/2008/10/15/regular-expression-limitations.aspx
你的示例中没有包含任何嵌套括号... 如果你不关心嵌套,那么可以使用以下表达式:
^[^()]*(?:\([^()]*\)[^()]*)*$
同意使用正则表达式无法实现这一点。不过,您可以尝试以下方法:
<?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;
}
?>
扩展JaredPar的答案,不使用正则表达式也可以很容易地解决,只需编写一个检查字符串中每个字符并增加/减少计数器的函数。如果找到“(”,则将其增加,如果找到“)”,则将其减少。如果计数器小于0,则可以中断,该字符串无效。当您处理整个字符串时,如果计数器不为0,则存在未匹配的开括号。
为什么正则表达式无法实现括号匹配
其他答案都是正确的,但我想强调一下理论计算机科学的重要性...这是一个知道理论可以带来实际优势的例子。
正则表达式对应于确定有限状态自动机(DFA),但括号匹配需要上下文无关文法,可以通过有限状态自动机(PDA)实现,但不能通过DFA实现。
因此,我们知道答案是否定的,而不必担心我们可能会忽略某些东西。所以,你可以对以上答案感到自信,并且不必担心作者在给出答案时是否忽略了某些东西。
几乎所有编译器书籍都会谈到这个问题,以下是一个简要概述:
不使用正则表达式的 PHP 编程:
function analyse($input){
$len = strlen($input);
$depth = 0;
for ($i = 0; $i < $len; $i++) {
$depth += $input[$i] == '(';
$depth -= $input[$i] == ')';
if ($depth < 0) break;
}
if ($depth != 0) return false;
else return true;
}
$check_nestled = analyse('(5 * 2) + ((2 + 2) - 4)');
if($check_nestled){
// do stuff, everything is ok
}