2009-12-18 5 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는 ("DEF"과 "456") 마지막으로 일치하는 문자열이 보인다. 나는 그룹에 의지해야한다는 것을 알기 위해 시간을 보냈다. 그룹 대신에 붙잡는다. 가치.

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(); 
} 

이 출력됩니다 : API를 디자인이 같은 이유를 이제

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 

, 나는 궁금. Group.Value가 마지막으로 일치하는 문자열 만 반환하는 이유는 무엇입니까? 이 디자인은 좋지 않습니다.

답변

2

주된 이유는 역사입니다. 정규 표현식은 항상 Perl과 그 이상으로 돌아가는 방식으로 항상 작동했습니다. 그러나 그것은 정말 나쁜 디자인이 아닙니다. 일반적으로 그런 모든 일치를 원하면 가장 바깥 쪽의 한정 기호 (+)를 그대로두고 Match() 대신 Matches() 메서드를 사용하면됩니다. 모든 정규식 사용 가능 언어는이를 수행 할 수있는 방법을 제공합니다. Perl이나 JavaScript에서는 /g 모드로 일치합니다. 루비에서는 scan 메소드를 사용합니다. Java에서는 false을 반환 할 때까지 find()을 반복적으로 호출합니다. 마찬가지로 바꾸기 작업을 수행하는 경우 자리 표시 자와 함께 캡처 된 하위 문자열을 다시 연결할 수 있습니다 (언어에 따라 $1, $2 또는 \1, \2).

다른 한편으로, .NET과 마찬가지로 CaptureCollections와 같은 중간 캡처 그룹 일치를 검색 할 수있는 Perl 5 파생 regex flavor는 없습니다. 그리고 저는 놀랄 일도 아닙니다. 실제로 모든 경기를 한 번에 캡처해야하는 경우는 거의 없습니다. 그리고 모든 중간 단계를 추적하기 위해 취할 수있는 모든 저장 및/또는 처리 능력에 대해 생각해보십시오. 그것은 좋은 기능입니다.