用于.NET的备用RegEx引擎,支持递归

时间:2011-08-02 16:50:55

标签: .net regex recursion

我遇到了一个解析问题,需要一个非常小的正则表达式来解决,除了要使用的模式,它应该是递归的。
例如:

{([^{}]*(?:{(?1)})?)

我希望它匹配,是一个特定的RTF标题,但要做到这一点,我需要它是递归的。

{\rtf1\ansi\ansicpg1252\deff0\deflang1031{\fonttbl{\f0\fnil\fcharset0 Tahoma;}}

是否存在某种类似.NET的非真实RegEx引擎实现,它可以找到这些模式的匹配(甚至可能是不同的语法)?

更新

我非常感谢大家告诉我有关正则表达式的.NET实现中的Balancing Group选项,尤其是Qtax,他提供了一个非常全面的链接作为下面的评论,这有助于我理解这是什么,以及发布我的具体例子的答案。如果您正在阅读本文,并且它也对您有帮助,请务必提供该答案 然而...... 这并没有回答关于.NET Regex类引擎中递归可能性的一般问题。这个例子,幸运的是(我喜欢挑战)是迄今为止我遇到的唯一一个。并且使用此解决方案无法解决其他情况,但只能通过引用不匹配,而是重用模式序列,到可以递归的点。

2 个答案:

答案 0 :(得分:3)

对于使用balancing group的示例,可以使用。

您可以使用如下表达式:

{
[^{}]*
(?:({)[^{}]*)*
(?'-1'})*
(?(1)(?!))
}

示例:

string re = @"{[^{}]*(?:({)[^{}]*)*(?'-1'})*(?(1)(?!))}";
string str = "foo {bar} baz {foo{bar{baz}}} {f{o{o}}{bar}baz} {foo{bar}baz}";

Console.WriteLine("Input: \"{0}\"", str);
foreach (Match m in Regex.Matches(str, re))
{
    Console.WriteLine("Match: \"{0}\"", m);
}

输出:

Input: "foo {bar} baz {foo{bar{baz}}} {f{o{o}}{bar}baz} {foo{bar}baz}"
Match: "{bar}"
Match: "{foo{bar{baz}}}"
Match: "{o{o}}"
Match: "{bar}"
Match: "{bar}"

答案 1 :(得分:3)

即使是Qtax例子也非常清楚,但它并不完全符合我,因为返回{o{o}}而不是{f{o{o}}{bar}baz}

在寻找一段时间之后,我的解决方案是(使用几乎相同的例子):

输入:

string re = @"{(((?<Counter>{)*[^{}]*)*((?<-Counter>})*[^{}]*)*)*(?(Counter)(?!))}";
string str = "foo {bar} baz {foo{bar{{baz}a{a{b}}}}} {f{o{o}}{bar{a{b{c}}{d}}}baz} {foo{bar}baz}";

Console.WriteLine("Input: \"{0}\"", str);
foreach (Match m in Regex.Matches(str, re))
{
    Console.WriteLine("Match: \"{0}\"", m);
}

输出:

Input: "foo {bar} baz {foo{bar{{baz}a{a{b}}}}} {f{o{o}}{bar{a{b{c}}{d}}}baz} {foo{bar}baz}"
Match: "{bar}"
Match: "{foo{bar{{baz}a{a{b}}}}}"
Match: "{f{o{o}}{bar{a{b{c}}{d}}}baz}"
Match: "{foo{bar}baz}"

一些解释,我为每个{增加一个计数器,并在每个}递减计数器。最后,仅当计数器为空((?(Counter)(?!)))时,正则表达式匹配。

它似乎适用于深度递归和替代支架。

请参阅此site,这也有助于我创建此正则表达式。

我希望这会有所帮助。

PS: 如果你想在最后匹配字符串和忘记},请使用:

string re = @"{(((?<Counter>{)*[^{}]*)*((?<-Counter>(}|$))*[^{}]*)*)*(?(Counter)(?!))(}|$)";
string str = "foo {bar} baz {foo{bar{{baz}a{a{b}}}}} {f{o{o}}{bar{a{b{c}}{d}}}baz} {foo{bar}b{az";