我遇到了一个解析问题,需要一个非常小的正则表达式来解决,除了要使用的模式,它应该是递归的。
例如:
{([^{}]*(?:{(?1)})?)
我希望它匹配,是一个特定的RTF标题,但要做到这一点,我需要它是递归的。
{\rtf1\ansi\ansicpg1252\deff0\deflang1031{\fonttbl{\f0\fnil\fcharset0 Tahoma;}}
是否存在某种类似.NET的非真实RegEx引擎实现,它可以找到这些模式的匹配(甚至可能是不同的语法)?
更新
我非常感谢大家告诉我有关正则表达式的.NET实现中的Balancing Group选项,尤其是Qtax,他提供了一个非常全面的链接作为下面的评论,这有助于我理解这是什么,以及发布我的具体例子的答案。如果您正在阅读本文,并且它也对您有帮助,请务必提供该答案 然而...... 这并没有回答关于.NET Regex类引擎中递归可能性的一般问题。这个例子,幸运的是(我喜欢挑战)是迄今为止我遇到的唯一一个。并且使用此解决方案无法解决其他情况,但只能通过引用不匹配,而是重用模式序列,到可以递归的点。
答案 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";