用于删除由有序字符集组成的嵌套括号的平衡匹配正则表达式是什么?

What is the balance matching regular expression for removing nested brackets composed of sets of ordered characters?

关注这个问题:

我正在尝试使用平衡匹配来替换括号内的所有项目,但在示例中括号是 "{{""}}"。而我的括号是 "<![CDATA[""]]>".

我无法修改上一个问题的已接受答案中正则表达式的 [^{}] 部分,以改用我的方括号版本。我试过把[^{}]改成(?!(<!\[CDATA\|\]\]>)).

我已将问题简化为使用 12 作为左括号,34 作为右括号。以下 returns "STST" 符合预期。

using System.Text.RegularExpressions;

Regex.Replace(
12T1212E343434STST12RING34',--input
'12(?!(12|34))*(((?<Open>12)(?!(12|34))*)+((?<Close-Open>34)(?!(12|34))*)+)*(?(Open)(?!))34',--pattern
''--replacement
);

但是,如果我将 12 替换为 <!\[CDATA\[" and 34 with "\]\]>,它就不起作用了。

最后,我想对以下 CDATA 示例字符串进行操作:

"<![CDATA[t<![CDATA[e]]>]]>stst<![CDATA[ring]]>"

应该return

"stst"

您当前的 12...34 匹配正则表达式不正确,因为使用的 是 "corrupt"((?!(12|34))* 缺少消费部分,.)。

你只需要记住正则表达式的部分:1) 前导分隔符模式,2) 尾随分隔符模式,3) 中间部分应该匹配不是 1 和 2 的部分,4 ) 检查 "technical" 组捕获堆栈是否为空的 conditional construct

因此,数字正则表达式可以固定为

12(?>(?!12|34).|(?<o>)12|(?<-o>)34)*(?(o)(?!))34

(regex demo) 而 CDATA 看起来像

<!\[CDATA\[(?>(?!<!\[CDATA\[|]]>).|(?<o>)<!\[CDATA\[|(?<-o>)]]>)*(?(o)(?!))]]>

this regex demo

注意:如果字符串输入中可以有换行符,请在模式处使用 RegexOptions.Singleline 选项或内联修饰符版本 (?s)开始。

图案详情:

  • 12 - 前导分隔符模式
  • (?> - 将匹配既不是前导模式也不是尾随模式的原子组的开始,并将跟踪那些定界子字符串:
    • (?!12|34).| - 匹配任何字符(如果使用 RegexOptions.Singleline 选项,甚至包括换行符)但作为 12 或 [=22= 起点的字符] 序列
    • (?<o>)12| - match12` 并递增 "o" 组捕获堆栈,或
    • (?<-o>)34 - 匹配 34 并递减 "o" 组捕获堆栈
  • )* - 并重复(保持匹配)原子组内模式的零次或多次出现
  • (?(o)(?!)) - 将检查 "o" 组捕获堆栈是否为空的条件构造。如果不为空,则触发回溯,查找均衡数量的leading/trailing个分隔符。
  • 34 - 尾随分隔符模式。

此外,<![CDATA[中的[必须进行转义,因为[是字符class之外的特殊字符,而[=中的] 33=] 不必转义,因为在字符 class 之外,] 对于 .NET 正则表达式来说并不特殊。