2009-12-18 45 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。我並不感到驚訝:實際上你很少需要像這樣一次性捕捉所有比賽。並考慮它可以用來跟蹤所有這些中間匹配的所有存儲和/或處理能力。不過這是一個很好的功能。

相關問題