2009-07-08 6 views
5

ein Verfahren istRegex: Benannte Gruppen und Ersatz

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

Der letzte Parameter Muster Ersatz wie ${groupName} und andere unterstützt (aber ich weiß nicht, die Gruppennamen in der Laufzeit).

In meinem Fall habe ich das dynamisch erzeugte Muster wie:

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

Mein Ziel ist es, jede Gruppe mit dem Wert je nach Gruppennamen zu ersetzen. Zum Beispiel wird das Wort "Wort1" durch <span class="c0">word1</span> ersetzt. Dies ist für Suchergebnisse wie Google.

Kann dies mit der obigen Methode ohne überladene Methode mit MatchEvaluator Parameter durchgeführt werden?

Vielen Dank im Voraus!

+0

würde ich mit MatchEvaluator gehen Sie einfach ... es funktioniert ... –

+0

Ja, danke! Eigentlich habe ich eine funktionierende Lösung mit MatchEvaluator. Aber wie elegant wäre eine Lösung mit nur einer Codezeile anstelle von sechs-sieben :) – Alex

Antwort

3

Ich denke nicht, dass die Verwendung des $ {groupname} in der von Ihnen vorgeschlagenen Weise möglich ist, es sei denn, ich missverstände den genauen Austausch, der ausgeführt wird. Der Grund dafür ist, dass die Ersetzungszeichenfolge so aufgebaut sein muss, dass sie jeden Gruppennamen berücksichtigt. Da sie dynamisch generiert werden, ist dies nicht möglich. Mit anderen Worten: Wie entwerfen Sie in einer Anweisung eine Ersatzzeichenfolge, die c0 ... cn abdeckt und ihre jeweiligen Erfassungswerte ersetzt? Du könntest die Namen durchlaufen, aber wie würdest du den modifizierten Text beibehalten, um 1 Ersatz pro Gruppennamen durchzuführen?

Ich habe jedoch eine mögliche Lösung für Sie. Es verwendet immer noch die MatchEvaluator-Überladung, aber mit einigen Lambda-Ausdrücken und LINQ können Sie dies auf 1 Zeile herunter bekommen. Ich werde es jedoch zur besseren Übersicht formatieren. Vielleicht passt das zu Ihren Bedürfnissen oder weist Sie in die richtige Richtung.

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

Ausgang:

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

Danke! Ich habe mein Problem auf diese Weise gelöst. Aber unter dem Begriff "eine Zeile" meinte ich etwas wie Regex.Replace (String-Quelle, String-Muster, " $ &"). Wobei $ {groupName} eine mythische Gruppennamenersetzung ist (funktioniert aber, wenn der Gruppenname bekannt ist;). Aber scheint es in meinem Fall unmöglich. Noch ein Dank für die Antwort! – Alex