我需要一个正则表达式来选择两个外括号之间的所有文本。

例子: START_TEXT(这里的文本(可能的文本)文本(可能的文本(更多的文本))END_TXT ^ ^

结果: (此处文本(可能的文本)文本(可能的文本(更多的文本)))


当前回答

虽然很多答案都以某种形式提到了这一点,比如正则表达式不支持递归匹配等等,但主要原因在于计算理论的根源。

形式为{a^nb^n | n>=0}的语言是非正则的。Regex只能匹配构成常规语言集一部分的东西。

阅读更多@这里

其他回答

这并没有完全解决OP问题,但我认为它可能对一些来这里搜索嵌套结构regexp的人有用:

在javascript中从函数字符串(带有嵌套结构)解析参数

匹配结构如下:

匹配方括号、方括号、圆括号、单引号和双引号

在这里您可以看到生成的regexp正在运行

/**
 * get param content of function string.
 * only params string should be provided without parentheses
 * WORK even if some/all params are not set
 * @return [param1, param2, param3]
 */
exports.getParamsSAFE = (str, nbParams = 3) => {
    const nextParamReg = /^\s*((?:(?:['"([{](?:[^'"()[\]{}]*?|['"([{](?:[^'"()[\]{}]*?|['"([{][^'"()[\]{}]*?['")}\]])*?['")}\]])*?['")}\]])|[^,])*?)\s*(?:,|$)/;
    const params = [];
    while (str.length) { // this is to avoid a BIG performance issue in javascript regexp engine
        str = str.replace(nextParamReg, (full, p1) => {
            params.push(p1);
            return '';
        });
    }
    return params;
};

我想添加这个答案,以便快速参考。请随时更新。


.NET Regex使用平衡组:

\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)

其中c用作深度计数器。

在Regexstorm.com上进行演示

堆栈溢出:使用正则表达式来平衡匹配括号 Wes令人困惑的博客:平衡结构与。net正则表达式的匹配 Greg Reinacker的Weblog:正则表达式中的嵌套结构


使用递归模式的PCRE:

\((?:[^)(]+|(?R))*+\)

演示在regex101;或无交替的:

\((?:[^)(]*(?R)?)*+\)

演示在regex101;或为表演而展开:

\([^)(]*+(?:(?R)[^)(]*)*+\)

演示在regex101;模式被粘贴在(?R)处,它表示(?0)。

Perl, PHP, notepad++, R: Perl =TRUE, Python: PyPI正则表达式模块与(?V1)的Perl行为。 (新版本的PyPI regex包已经默认为this→DEFAULT_VERSION = VERSION1)


Ruby使用子表达式调用:

与Ruby 2.0 \g<0>可以用来调用完整的模式。

\((?>[^)(]+|\g<0>)*\)

在Rubular演示;Ruby 1.9只支持捕获组递归:

(\((?>[^)(]+|\g<1>)*\))

Rubular的演示(从Ruby 1.9.3开始进行原子分组)


API JavaScript

XRegExp.matchRecursive(str, '\\(', '\\)', 'g');

Java: @jaytea使用前向引用的有趣想法。


不递归最多3层嵌套: (JS, Java和其他类型的正则表达式)

为了防止不平衡时失控,只在最内层[)(]上使用*。

\((?:[^)(]|\((?:[^)(]|\((?:[^)(]|\([^)(]*\))*\))*\))*\)

演示在regex101;或展开以获得更好的性能(首选)。

\([^)(]*(?:\([^)(]*(?:\([^)(]*(?:\([^)(]*\)[^)(]*)*\)[^)(]*)*\)[^)(]*)*\)

演示在regex101;需要根据需要添加更深层次的嵌套。


参考-这个正则表达式是什么意思?

递归正则表达式 Regular- expressions .info -正则表达式递归 精通正则表达式- Jeffrey E.F. Friedl 1 2 3 4

你可以使用regex递归:

\(([^()]|(?R))*\)

这个答案解释了为什么正则表达式不是这项任务的正确工具的理论局限性。


正则表达式不能做到这一点。

正则表达式基于有限状态自动机(FSA)的计算模型。顾名思义,FSA只能记住当前状态,它没有关于以前状态的信息。

在上图中,S1和S2是两种状态,其中S1是开始和结束步骤。因此,如果我们尝试使用字符串0110,转换如下:

      0     1     1     0
-> S1 -> S2 -> S2 -> S2 ->S1

在上述步骤中,当我们在第二个S2,即解析完0110的01之后,FSA没有关于01中前一个0的信息,因为它只能记住当前状态和下一个输入符号。

在上面的问题中,我们需要知道左括号的no;这意味着它必须存储在某个地方。但是由于fsa不能这样做,因此不能编写正则表达式。

但是,可以编写一个算法来完成这项任务。算法一般属于下推自动机(PDA)。PDA比FSA高一级。PDA有一个额外的堆栈来存储一些额外的信息。pda可以用来解决上述问题,因为我们可以在堆栈中“推入”开括号,并在遇到闭括号时“弹出”它们。如果在结束时,堆栈为空,则开始括号和结束括号匹配。否则不。

(?<=\().*(?=\))

如果您想在两个匹配的括号之间选择文本,那么使用正则表达式就不太走运了。这是不可能的。

这个正则表达式只返回字符串中第一个开始括号和最后一个结束括号之间的文本。


(*)除非你的regex引擎有像平衡组或递归这样的特性。支持这些特性的引擎的数量正在缓慢增长,但它们仍然不是普遍可用的。