【问题标题】:Alternative RegEx engine for .NET, supporting recursion.NET 的替代 RegEx 引擎,支持递归
【发布时间】:2011-08-02 16:50:54
【问题描述】:

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

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

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

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

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

更新:

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

【问题讨论】:

  • 虽然不是递归的直接答案,但 .NET 对 Balanced Trees 的支持可能对这个问题有用。
  • 手册中的平衡组:msdn.microsoft.com/en-us/library/…
  • 是的,我确实觉得这很有帮助,谢谢。然而,这并不是我需要递归正则表达式的唯一情况。

标签: .net regex recursion


【解决方案1】:

对于您的示例,使用 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}"

【讨论】:

  • 不是这个特定问题的完整答案,但最接近,它确实有帮助。谢谢。
【解决方案2】:

即使是 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";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2011-12-23
    • 2022-11-23
    • 2011-04-08
    相关资源
    最近更新 更多