是否有能够解析匹配符号的正则表达式?

Mai*_*tor 1 regex string parsing

这个正则表达式

/\(.*\)/
Run Code Online (Sandbox Code Playgroud)

将不匹配匹配的括号,但匹配字符串中的最后一个括号.是否有正则表达式扩展或类似的东西,具有适当的语法允许这个?例如:

there are (many (things (on) the)) box (except (carrots (and apples)))
Run Code Online (Sandbox Code Playgroud)

/OPEN(.*CLOSE)/ 应该匹配 (many (things (on) the))

可能有无限级别的括号.

Mar*_*der 7

如果你只有一个级别的括号,那么有两种可能性.

选项1:使用不合理的重复:

/\(.*?\)/
Run Code Online (Sandbox Code Playgroud)

这将在遇到第一个时停止).

选项2:使用否定字符类

/\([^)]*\)/
Run Code Online (Sandbox Code Playgroud)

这只能重复不重复的字符),因此它必然不会超过第一个右括号.由于性能原因,通常首选此选项.此外,此选项更容易扩展以允许转义括号(以便您可以匹配此完整字符串:(some\)thing)而不是丢弃thing)).但这可能很少需要.

但是,如果你想要嵌套结构,这对于正则表达式来说通常过于复杂(尽管像PCRE这样的一些版本支持递归模式).在这种情况下,您应该自己查看字符串并计算括号,以跟踪当前的嵌套级别.

正如关于这些递归模式的旁注:在PCRE中(?R)只是代表整个模式,因此将其插入某处会使整个事物递归.但是,括号中的每个内容必须与整个匹配的结构相同.此外,实际上不可能对此进行有意义的一步替换,以及在多个嵌套级别上使用捕获组.总而言之 - 你最好不要使用正则表达式来嵌套结构.

更新:由于您似乎渴望找到正则表达式解决方案,以下是使用PCRE匹配示例的方法(PHP中的示例实现):

$str = 'there are (many (things (on) the)) box (except (carrots (and apples)))';
preg_match_all('/\([^()]*(?:(?R)[^()]*)*\)/', $str, $matches);
print_r($matches);
Run Code Online (Sandbox Code Playgroud)

结果是

Array
(
    [0] => Array
        (
            [0] => (many (things (on) the))
            [1] => (except (carrots (and apples)))
        )   
)
Run Code Online (Sandbox Code Playgroud)

模式的作用:

\(      # opening bracket
[^()]*  # arbitrarily many non-bracket characters
(?:     # start a non-capturing group for later repetition
(?R)    # recursion! (match any nested brackets)
[^()]*  # arbitrarily many non-bracket characters
)*      # close the group and repeat it arbitrarily many times
\)      # closing bracket
Run Code Online (Sandbox Code Playgroud)

这允许无限的嵌套级别以及无限的并行级别.

请注意,不可能将所有嵌套级别作为单独的捕获组.你将始终只是获得最内层或最外层的组.此外,不能像这样进行递归替换.