2009-07-08 5 views
5

메소드가 있습니다.정규식 : 명명 된 그룹 및 바꾸기

Regex.Replace(string source, string pattern, string replacement) 

마지막 매개 변수는 ${groupName} 및 기타와 같은 패턴 대체를 지원합니다 (그러나 런타임에는 그룹 이름을 알 수 없습니다).

제 경우에는 다음과 같이 동적으로 생성 된 패턴이 있습니다 :

(?<c0>word1)|(?<c1>word2)|(?<c2>word3) 

내 목적은 각 그룹을 그룹 이름에 따라 값으로 대체하는 것입니다. 예를 들어, 단어 "word1"은 <span class="c0">word1</span>로 바뀝니다. 이것은 Google과 같은 검색 결과를 강조하기위한 것입니다.

MatchEvaluator 매개 변수로 오버로드 된 메서드를 사용하지 않는 위의 메서드를 사용하여이 작업을 수행 할 수 있습니까?

미리 감사드립니다!

+0

난 그냥 MatchEvaluator와 함께 가고 싶어 ... 작동 ... –

+0

네, 감사합니다! 사실 나는 MatchEvaluator와 함께 작동하는 솔루션을 가지고있다. 하지만 얼마나 우아한 코드가 6 행 7 대신에 한 줄의 코드로만 이루어질 수 있습니다. – Alex

답변

3

수행중인 정확한 대체를 오해하지 않는 한 제안한 방식으로 $ {groupname}을 (를) 사용하는 것이 가능하다고 생각하지 않습니다. 그 이유는 대체 문자열이 각 그룹 이름을 설명하는 방식으로 구성되어야하기 때문입니다. 동적으로 생성되기 때문에 이것이 가능하지 않습니다. 즉, 1 문장에서 c0 ... cn을 포함하는 대체 문자열을 설계하고 각각의 캡처 값을 대체하는 방법은 무엇입니까? 이름을 반복 할 수 있지만 수정 된 텍스트를 그대로 유지하여 그룹 이름 당 1 대체를 수행하는 방법은 무엇입니까?

그래도 가능한 해결책이 있습니다. 여전히 MatchEvaluator 오버로드를 사용하지만 일부 람다 식과 LINQ를 사용하면이 값을 1 줄로 줄일 수 있습니다. 그러나 아래의 내용을 명확히하기 위해 형식을 지정합니다. 아마도 이것은 귀하의 필요에 부합하거나 올바른 방향으로 당신을 가리킬 것입니다.

string text = @"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog."; 
string[] searchKeywords = { "quick", "fox", "lazy" }; 

// build pattern based on keywords - you probably had a routine in place for this 
var patternQuery = searchKeywords 
         .Select((s, i) => 
          String.Format("(?<c{0}>{1})", i, s) + 
          (i < searchKeywords.Length - 1 ? "|" : "")) 
         .Distinct(); 
string pattern = String.Join("", patternQuery.ToArray()); 
Console.WriteLine("Dynamic pattern: {0}\n", pattern); 

// use RegexOptions.IgnoreCase for case-insensitve search 
Regex rx = new Regex(pattern); 

// Notes: 
// - Skip(1): used to ignore first groupname of 0 (entire match) 
// - The idea is to use the groupname and its corresponding match. The Where 
// clause matches the pair up correctly based on the current match value 
// and returns the appropriate groupname 
string result = rx.Replace(text, m => String.Format(@"<span class=""{0}"">{1}</span>", 
        rx.GetGroupNames() 
        .Skip(1) 
        .Where(g => m.Value == m.Groups[rx.GroupNumberFromName(g)].Value) 
        .Single(), 
        m.Value)); 

Console.WriteLine("Original Text: {0}\n", text); 
Console.WriteLine("Result: {0}", result); 

출력 :

Dynamic pattern: (?<c0>quick)|(?<c1>fox)|(?<c2>lazy) 

Original Text: The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 

Result: The <span class="c0">quick</span> brown <span class="c1">fox</span> jumps over the <span class="c2">lazy</span> dog. The <span class="c0">quick</span> brown <span class="c1">fox</span> jumps over the <span class="c2">lazy</span> dog. 
+0

고마워요! 그런 방식으로 내 문제를 해결했습니다. 그러나 "한 줄"용어 아래에서 Regex.Replace (문자열 소스, 문자열 패턴, " $ &"와 같은 의미)를 의미했습니다. 여기서 $ {groupName}은 신화적인 그룹 이름 대체입니다 (그러나 그룹 이름을 알고있을 때 작동합니다). 하지만 내 경우에는 불가능한 것 같습니다. 답장을 보내 주셔서 감사합니다. – Alex