用于匹配n个括号的正则表达式

时间:2012-05-16 16:01:42

标签: regex

我需要解析以下形式的表达式:

(S(A(B(D xyz))(C m)))

(的量总是等于)的量,但在(S)之间可以有任意数量的开括号和右括号对。在这种情况下,我想提取(A(B(D xyz))(C m))。文件中可能有任意数量的(S)子句,所以我不能简单地进行^(S。*)$类型的模式匹配。

如果我知道(S)之间可能的开括号和右括号对的数量,这不会那么困难,但我不知道如何编写一个能够匹配任意数量的正则表达式( )。

非常感谢获得正则表达式模式的任何帮助。提前谢谢。

3 个答案:

答案 0 :(得分:1)

这不能在理论上完成,并且只有在预先知道最大数量的嵌套括号时才能在实践中完成。这个解决方案需要一个相当不愉快的表达,并且通常被尝试作为好奇的家庭作业。这里有一个link,可以更好地解释为什么regexp语言不足以解决匹配的括号问题。

你需要一个解析器来解决这个问题;一个简单的recursive descent就可以了。上面链接中的维基百科文章在C中有一个示例实现,您应该可以相对轻松地将其翻译成其他语言。

答案 1 :(得分:1)

使用纯正则表达式匹配任意数字是不可能的。换句话说,当您无法生成/编写正则表达式时,您无法匹配未知的计数。只要您在生成正则表达式时知道n,就可以匹配n对(无论多高n)。

答案 2 :(得分:0)

记录下降解析可能是最好的选择。但是如果你只是想找到(S)平衡,可以使用在引擎中进行递归的正则表达式来完成。

它会找到最大的平衡点。如果您希望嵌套(S(S))可能涉及递归调用实现正则表达式的函数,则传递成功匹配的“核心”。并且可能在此过程中创建父子结构。但如果涉及到它,那么真正的解析器可能就是解决方案。

如何使用Perl正则表达式解决 -

$str = '(some (stuff  (S (A (B (D xyz)) (C m))) the end ) (S extra))';

$regex = qr~
[(]
\s* S \s*
(                   # 1
    (                       # 2
      [(]
      (?:  (?> [^()]+ ) 
        |  (?2)                                         
      )*                                               
      [)]
    )
 |
    [^)]*
)
[)]
~x;

while ($str =~ /$regex/g)
{
    print "found '$1'\n";
}

打印

found '(A (B (D xyz)) (C m))'
found 'extra'