处理正则表达式中的嵌套括号

时间:2014-11-04 17:34:58

标签: java regex

当我有一套完整的最大深度为5的嵌套括号时,我希望我的正则表达式匹配。我当前的代码正在运行,但是它具有可怕的时间复杂度,并且对于长括号集需要很长时间。

^((\\((\\((\\((\\((\\(\\))*\\)(\\(\\))*)*\\))*\\))*(\\((\\((\\((\\(\\))*\\)(\\(\\))*)*\\))*\\))*\\))*)$

示例:

String s = (()());
System.out.println(s.matches(...));

- > 打印真实。

String s = ()));
System.out.println(s.matches(...));

- > 打印错误。

如何更改当前代码,使其不仅更高效,而且更容易阅读? 请注意,我确实希望在正则表达式中完成此操作,并且我知道使用for循环非常简单。 谢谢!

4 个答案:

答案 0 :(得分:2)

严格的正则表达式(http://en.wikipedia.org/wiki/Regular_expression)无法做到这一点。 现实生活中的编程语言都有"扩展"正则表达式,或多或少以性能为代价。

你需要的(在数学方面)是一个下推自动机(http://en.wikipedia.org/wiki/Pushdown_automaton)。

答案 1 :(得分:2)

如果您只查找最大深度为5,则可以使用以下正则表达式

(\((\((\((\((\(\))*\))*\))*\))*\))*

您可以在http://regex101.com/r/zN1sZ2/1

预先显示结果

这里的奖励是一些可用于生成此字符串的伪代码

var s = "_", depth = 5;
while(depth > 0) {
    s = s.replace("_", "(\\(_\\))*");
    depth--;
}
s = s.replace("_", "");

现在就像更改一个变量(depth)一样简单,如果您的需求发生变化并使用字符串s来执行正则表达式

答案 2 :(得分:0)

你将超越5个级别 格式化时,它应形成类似>符号的形状 5级深。

除此之外,你应该使外括号不可选 (此处,使用RegexFormat 5格式化和测试)

 #  "(\\((\\((\\((\\((\\(\\))*\\))*\\))*\\))*\\))"

 #^ 
 (                             # (1 start)
      \(
      (                             # (2 start)
           \(
           (                             # (3 start)
                \(
                (                             # (4 start)
                     \(
                     (                             # (5 start)
                          \(\)
                     )*                            # (5 end)
                     \)
                )*                            # (4 end)
                \)
           )*                            # (3 end)
           \)
      )*                            # (2 end)
      \)
 )                             # (1 end)
 # $ 

输出样本:

 **  Grp 0 -  ( pos 63 , len 20 ) 
(()()()()((()()())))  
 **  Grp 1 -  ( pos 63 , len 20 ) 
(()()()()((()()())))  
 **  Grp 2 -  ( pos 63 , len 20 ) 
(()()()()((()()())))  
 **  Grp 3 -  ( pos 72 , len 10 ) 
((()()()))  
 **  Grp 4 -  ( pos 73 , len 8 ) 
(()()())  
 **  Grp 5 -  ( pos 78 , len 2 ) 
()  

如果您为重复引入群集组,则可以捕获
更多内在的内容。
无法完整地完成它,可能使用C#及其
捕获可以完成的集合。

 #  "(\\(((?:\\(((?:\\(((?:\\(((?:\\(\\))*)\\))*)\\))*)\\))*)\\))"

 #^ 
 (                             # (1 start)
      \(

      (                             # (2 start)
           (?:
                \(
                (                             # (3 start)
                     (?:
                          \(
                          (                             # (4 start)
                               (?:
                                    \(
                                    (                             # (5 start)
                                         (?:
                                              \(\)
                                         )*
                                    )                             # (5 end)
                                    \)
                               )*
                          )                             # (4 end)
                          \)
                     )*
                )                             # (3 end)
                \)
           )*
      )                             # (2 end)
      \)
 )                             # (1 end)
 # $ 

输出:

 **  Grp 0 -  ( pos 3 , len 42 ) 
((()()()()((()()())))(()()()()((()()()))))  
 **  Grp 1 -  ( pos 3 , len 42 ) 
((()()()()((()()())))(()()()()((()()()))))  
 **  Grp 2 -  ( pos 4 , len 40 ) 
(()()()()((()()())))(()()()()((()()())))  
 **  Grp 3 -  ( pos 25 , len 18 ) 
()()()()((()()()))  
 **  Grp 4 -  ( pos 34 , len 8 ) 
(()()())  
 **  Grp 5 -  ( pos 35 , len 6 ) 
()()()  

答案 3 :(得分:0)

使用由内而外的方法轻松完成。这是一个正则表达式,它有效地匹配最内层的匹配括号:

正则表达式匹配最里面的括号对

\([^()]*\)

这是一个经过测试的JavaScript函数,它迭代地应用上面的正则表达式从内到外去掉所有匹配的对,同时计算嵌套级别:

function isBalanced5deeporLess(text) {
    var depth = 0;
    var re_inner_paren = /\([^()]*\)/g;
    while (text.search(re_inner_paren) !== -1) {
        text = text.replace(re_inner_paren, '');
        depth++;    // count nesting depth level.
    }
    if (text.length === 0 && depth <= 5) { return true; }
    return false;
}

正如您所看到的,可以轻松修改所需的嵌套深度以适应。我不是一个真正的Java人,但这个逻辑应该很容易翻译。