灾难性回溯;用于提取嵌套括号中的值的正则表达式



我想使用正则表达式从以下字符串中提取aaabb b={{b}}bb bbb{ccc} ccc

zyx={aaa}, yzx={bb b={{b}}bb bbb}, xyz={{ccc} ccc}

注意:aaa表示任意数量的字符的任意序列,因此没有确定的长度或模式。例如,{ccc} ccc可以是{cccccccccc}cc {cc} cccc cccc,或任何其他组合(,

我已经编写了以下正则表达式:

(?<a>[^{}]*)s*=s*{((?<v>[^{}]+)*)},*

此表达式提取aaa,但由于嵌套的花括号,无法解析输入的其余部分,导致灾难性的回溯失败。

关于如何更新regex以正确处理嵌套括号,有什么想法吗?

(以防万一,如果你需要特定于引擎的选项,我会使用C#.NET Core 3.0。此外,我不想在代码上做任何魔术,而是只使用正则表达式模式。(


类似问题

匹配平衡括号的问题正则表达式与此问题类似,不同之处在于这里的括号不一定是平衡的,而是遵循x={y}模式。


更新1

以下输入也是可能的:

yzx={bb b={{b}},bb bbb,}, 

注意{{b}}bbb之后的,


更新2

我写了以下模式,这可以匹配第一个例子中的aaa以外的任何内容:

(?<A>[^{}]*)s*=s*{(?<V>(?<S>([^{}]?){(?:[^}{]+|(?&S))+}))}(,|$)

Regex匹配,非常好

CCD_ 13可以工作。

string input = "zyx={aaa}, yzx={bb b={{b}}bb bbb}, yzx={bb b={{b}},bb bbb,}, xyz={{ccc} ccc}";
string pattern = "={(.*?)}(, |$)";
var matches = Regex.Matches(input, pattern)
.Select(m => m.Groups[1].Value)
.ToList();
foreach (var m in matches) Console.WriteLine(m);

输出

aaa
bb b={{b}}bb bbb
bb b={{b}},bb bbb,
{ccc} ccc

Regex。斯普利特,真的很好

我认为对于这份工作来说,Regex.Split可能是一个更好的工具。

tring input = "zyx={aaa}, yzx={bb b={{b}}bb bbb}, yzx={bb b={{b}},bb bbb,}, ttt={nasty{t, }, }, xyz={{ccc} ccc}, zzz={{{{{{{huh?}";
var matches2 = Regex.Split(input, "(^|, )[a-zA-Z]+=", RegexOptions.ExplicitCapture); // Or "(?:^|, )[a-zA-Z]+=" without the flag

Console.WriteLine("-------------------------"); // Adding this to show the empty element (see note below)
foreach (var m in matches2) Console.WriteLine(m);
Console.WriteLine("-------------------------");
-------------------------
{aaa}
{bb b={{b}}bb bbb}
{bb b={{b}},bb bbb,}
{nasty{t, }, }
{{ccc} ccc}
{{{{{{{huh?}
-------------------------

注意:空元素存在是因为:

如果在输入字符串的开头或结尾找到匹配项,则在返回数组的开头或末尾会包含一个空字符串。

案例3

string input = "AAA={aaa}, BBB={bbb, bb{{b}}, bbb{b}}, CCC={ccc}, DDD={ddd}, EEE={00-99} ";
var matches2 = Regex.Split(input, "(?:^|, )[a-zA-Z]+="); // Or drop '?:' and use RegexOptions.ExplicitCapture
foreach (var m in matches2) Console.WriteLine(m);

{aaa}
{bbb, bb{{b}}, bbb{b}}
{ccc}
{ddd}
{00-99} 

最新更新