代码之家  ›  专栏  ›  技术社区  ›  Peter Lee

贪婪,非贪婪,所有贪婪匹配

  •  21
  • Peter Lee  · 技术社区  · 16 年前

    // 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、 我想把所有的比赛都用一般的方式进行。上面的例子只是一个例子。

    3 回复  |  直到 9 年前
        1
  •  21
  •   Luke Girvin Nathan Bedford    10 年前

    你可以用这样的方法:

    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.*?");
    
        2
  •  6
  •   Alan Moore Chris Ballance    16 年前

    如果存在解决方案,则可能涉及捕获组和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

        3
  •  1
  •   Tahbaza    16 年前

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