24

如何获得以下示例中的所有匹配项:

// 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"

PS:我想以通用方式进行所有匹配。上面的例子只是一个例子。

4

3 回答 3

23

你可以使用类似的东西:

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.*?");
于 2010-10-09T23:06:00.807 回答
6

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

我说“如果”是因为,虽然它适用于您的简单测试用例,但我不能保证这个技巧会帮助您解决实际问题。 RightToLeftmode 是 .NET 更具创新性的功能之一——即兴发挥,我想不出另一种风格可以与之等效。它的官方文档很少(委婉地说),到目前为止似乎没有很多开发人员使用它并在线分享他们的经验。所以尝试一下,看看会发生什么。

于 2010-10-10T01:05:33.170 回答
1

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

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

于 2010-10-09T22:50:20.660 回答