C#Regex中的贪婪,非贪婪,全贪婪的匹配

时间:2010-10-09 22:48:30

标签: c# regex greedy regex-greedy non-greedy

如何在以下示例中获取所有匹配项:

// Only "abcd" is matched
MatchCollection greedyMatches = Regex.Matches("abcd", @"ab.*");

// Only "ab" is matched
MatchCollection lazyMatches   = Regex.Matches("abcd", @"ab.*?");

// How can I get all matches: "ab", "abc", "abcd"

P.S。:我希望以通用的方式进行所有比赛。上面的例子只是一个例子。

3 个答案:

答案 0 :(得分:19)

您可以使用以下内容:

MatchCollection nonGreedyMatches = Regex.Matches("abcd", @"(((ab)c)d)");

那么你应该对ab,abc和abcd有三个反向引用。

但是,说实话,这种正则表达式并没有多大意义,特别是当它变大时变得难以理解。

修改

MatchCollection nonGreedyMatches = Regex.Matches("abcd", @"ab.?");

你有错误。这只能匹配ab和abc(读取:ab +任意(可选)字符

懒惰版:

MatchCollection greedyMatches    = Regex.Matches("abcd", @"ab.*");

是:

MatchCollection nonGreedyMatches    = Regex.Matches("abcd", @"ab.*?");

答案 1 :(得分:4)

如果存在解决方案,则可能涉及捕获组和RightToLeft选项:

string s = @"abcd";
Regex r = new Regex(@"(?<=^(ab.*)).*?", RegexOptions.RightToLeft);
foreach (Match m in r.Matches(s))
{
  Console.WriteLine(m.Groups[1].Value);
}

输出:

abcd
abc
ab

我说“if”因为虽然它适用于您的简单测试用例,但我不能保证这个技巧会对您的现实问题有所帮助。 RightToLeft模式是.NET更具创新性的功能之一 - 另外,我无法想到另一种与之相当的东西。关于它的官方文档很少(说得温和),到目前为止似乎没有很多开发人员使用它并在线分享他们的经验。所以试试看看会发生什么。

答案 2 :(得分:1)

只有一场比赛你不能得到三个不同的结果。

如果您只想匹配“ab”,可以使用ab.?a.{1}(或许多其他选项)
如果您只想匹配“abc”,可以使用ab.a.{2}(或许多其他选项)
如果您只想匹配“abcd”,可以使用ab.*a.{3}(或许多其他选项)