2009-07-08 20 views
5

C'è un metodoRegex: Chiamato gruppi e sostituzioni

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

L'ultimo parametro supporta le sostituzioni del modello, come ${groupName} e altri (ma non so il nome del gruppo nella fase di esecuzione).

Nel mio caso ho il modello creato in modo dinamico come:

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

Il mio scopo è quello di sostituire ogni gruppo con il valore a seconda del nome del gruppo. Ad esempio, la parola "word1" verrà sostituita con <span class="c0">word1</span>. Questo è per risultati di ricerca evidenziando come google.

È possibile farlo utilizzando il metodo sopra non utilizzando il metodo sovraccarico con il parametro MatchEvaluator?

Grazie in anticipo!

+0

avevo appena andare con MatchEvaluator ... funziona ... –

+0

Sì, grazie! In realtà ho una soluzione funzionante con MatchEvaluator. Ma quanto sarebbe elegante una soluzione con una sola riga di codice invece di sei-sette :) – Alex

risposta

3

Non penso che l'uso del $ {groupname} nel modo suggerito sia fattibile a meno che non fraintendano l'esatta sostituzione che viene eseguita. Il motivo è che la stringa di sostituzione deve essere costruita in modo tale che rappresenti il ​​nome di ciascun gruppo. Dal momento che sono generati dinamicamente questo non lo rende possibile. In altre parole, come, in una dichiarazione, progettate una stringa sostitutiva che copra c0 ... cn e sostituisca i rispettivi valori di cattura? È possibile scorrere i nomi, ma come si manterrebbe intatto il testo modificato per eseguire 1 sostituzione per nome di gruppo?

Ho una soluzione possibile per te. Usa ancora il sovraccarico di MatchEvaluator, ma con alcune espressioni lambda e LINQ puoi ridurlo a 1 riga. Tuttavia, lo formatterò per chiarezza qui sotto. Forse questo si adatta alle tue esigenze o ti indirizza nella giusta direzione.

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

uscita:

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

Grazie! Ho risolto il mio problema in questo modo. Ma sotto il termine "una riga" intendevo qualcosa come Regex.Replace (stringa di origine, tipo di stringa, " $ &"). Dove $ {groupName} è una sostituzione del nome di un gruppo mitico (ma funziona quando il nome del gruppo è noto;). Ma sembra impossibile nel mio caso. Ancora grazie per la risposta! – Alex

Problemi correlati