tch*_*ist 21
所有这些答案声称你不能使用模式来匹配具有平衡嵌套parens的字符串是非常错误的.假装现代编程语言匹配的模式仅限于病理教科书意义上的"常规语言"是不切实际的.一旦你允许反向引用,它们就不会.这使得真实世界的模式比教科书版本更匹配,使它们更加实用.
匹配平衡parens的最简单模式是\((?:[^()]*+|(?0))*\)
.但是你永远不应该这样写,因为它太紧凑而不易读.您应该始终使用/x
模式编写它以允许空格和注释.所以这样写:
m{
\( # literal open paren
(?: # begin alternation group
[^()]*+ # match nonparens possessively
| # or else
(?0) # recursively match entire pattern
)* # repeat alternation group
\) # literal close paren
}x
Run Code Online (Sandbox Code Playgroud)
对于命名抽象,并将它们的定义及其排序与执行分离,还有很多要说的.这导致了这种情况:
my $nested_paren_rx = qr{
(?&nested_parens)
(?(DEFINE)
(?<open> \( )
(?<close> \) )
(?<nonparens> [^()] )
(?<nested_parens>
(?&open)
(?:
(?&nonparens) *+
|
(?&nested_parens)
) *
(?&close)
)
)
}x;
Run Code Online (Sandbox Code Playgroud)
第二种形式现在可以包含在更大的模式中.
不要让任何人告诉你不能使用模式来匹配递归定义的东西.正如我刚才所说,你当然可以.
当你在它的时候,确保永远不要写线噪声模式.你不必,你不应该.没有编程语言可以维护,禁止使用空格,注释,子例程或字母数字标识符.所以在你的模式中使用所有这些东西.
当然,它确实有助于为这种工作选择正确的语言.☺
如果您遇到正则表达式语法不支持递归匹配的语言,我会给您简单的Javascript实现,您应该可以使用您选择的语言创建自己的语言:
function testBraces(s) {
for (var i=0, j=0; i<s.length && j>=0; i++)
switch(s.charAt(i)) {
case '(': { j++ ; break; }
case ')': { j-- ; break; }
}
return j == 0;
}
Run Code Online (Sandbox Code Playgroud)
在这里你可以玩它:http://jsfiddle.net/BFsn2/