2009-12-18 69 views
0

最近,我发现一个C#Regex API真的很烦人。为什么Group.Value总是最后匹配的组串?

我有正则表达式(([0-9]+)|([a-z]+))+。我想查找所有匹配的字符串。代码如下所示。

string regularExp = "(([0-9]+)|([a-z]+))+"; 
string str = "abc123xyz456defFOO"; 

Match match = Regex.Match(str, regularExp, RegexOptions.None); 
int matchCount = 0; 

while (match.Success) 
{ 
    Console.WriteLine("Match" + (++matchCount)); 

    Console.WriteLine("Match group count = {0}", match.Groups.Count); 
    for (int i = 0; i < match.Groups.Count; i++) 
    { 
     Group group = match.Groups[i]; 
     Console.WriteLine("Group" + i + "='" + group.Value + "'"); 
    } 

    match = match.NextMatch(); 
    Console.WriteLine("go to next match"); 
    Console.WriteLine(); 
} 

输出是:

Match1 
Match group count = 4 
Group0='abc123xyz456def' 
Group1='def' 
Group2='456' 
Group3='def' 
go to next match 

似乎所有group.Value是最后一个匹配的字符串( “高清” 和 “456”)。我花了一些时间弄清楚我应该依靠group.Captures而不是group.Value。

string regularExp = "(([0-9]+)|([a-z]+))+"; 
string str = "abc123xyz456def"; 
//Console.WriteLine(str); 

Match match = Regex.Match(str, regularExp, RegexOptions.None); 
int matchCount = 0; 

while (match.Success) 
{ 
    Console.WriteLine("Match" + (++matchCount)); 

    Console.WriteLine("Match group count = {0}", match.Groups.Count); 
    for (int i = 0; i < match.Groups.Count; i++) 
    { 
     Group group = match.Groups[i]; 
     Console.WriteLine("Group" + i + "='" + group.Value + "'"); 

     CaptureCollection cc = group.Captures; 
     for (int j = 0; j < cc.Count; j++) 
     { 
      Capture c = cc[j]; 
      System.Console.WriteLine(" Capture" + j + "='" + c + "', Position=" + c.Index); 
     } 
    } 

    match = match.NextMatch(); 
    Console.WriteLine("go to next match"); 
    Console.WriteLine(); 
} 

这将输出:

Match1 
Match group count = 4 
Group0='abc123xyz456def' 
    Capture0='abc123xyz456def', Position=0 
Group1='def' 
    Capture0='abc', Position=0 
    Capture1='123', Position=3 
    Capture2='xyz', Position=6 
    Capture3='456', Position=9 
    Capture4='def', Position=12 
Group2='456' 
    Capture0='123', Position=3 
    Capture1='456', Position=9 
Group3='def' 
    Capture0='abc', Position=0 
    Capture1='xyz', Position=6 
    Capture2='def', Position=12 
go to next match 

现在,我很奇怪,为什么API的设计是这样的。为什么Group.Value只返回最后匹配的字符串?这种设计看起来不太好。

回答

2

主要原因是历史:正则表达式总是以这种方式工作,回到Perl及更高版本。但这不是非常糟糕的设计。通常情况下,如果你想要这样的每一场比赛,你只是离开最外面的量词(在这种情况下+),并使用Matches()方法,而不是Match()。每种支持正则表达式的语言都提供了一种方法:在Perl或JavaScript中,您可以在/g模式下进行匹配;在Ruby中,您使用scan方法;在Java中,您重复调用find(),直到它返回false。同样,如果您正在执行替换操作,则可以使用占位符($1,$2\1,\2,取决于语言)插入捕获的子字符串。另一方面,我知道没有其他的Perl 5派生的正则表达式可以检索像.NET一样的中间捕获组匹配,并且可以捕获它的CaptureCollections。我并不感到惊讶:实际上你很少需要像这样一次性捕捉所有比赛。并考虑它可以用来跟踪所有这些中间匹配的所有存储和/或处理能力。不过这是一个很好的功能。

相关问题