2009-07-08 14 views
5

hay un métodoRegex: Nombrado grupos y reemplazos

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

El último parámetro es compatible con los reemplazos de patrones tales como ${groupName} y otros (pero no sé el nombre del grupo en el tiempo de ejecución).

En mi caso tengo el patrón creado de forma dinámica como:

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

Mi propósito es reemplazar cada grupo con el valor en función de nombre de grupo. Por ejemplo, la palabra "word1" se reemplazará por <span class="c0">word1</span>. Esto es para los resultados de búsqueda que destacan como google.

¿Es posible hacerlo utilizando el método anterior que no utiliza el método sobrecargado con el parámetro MatchEvaluator?

¡Gracias de antemano!

+0

yo sólo iría con MatchEvaluator ... funciona ... –

+0

Sí, gracias! En realidad, tengo una solución de trabajo con MatchEvaluator. Pero qué tan elegante sería una solución con solo una línea de código en lugar de seis y siete :) – Alex

Respuesta

3

No creo que usar $ {groupname} en la manera que sugirió es factible a menos que no esté entendiendo el reemplazo exacto que se está realizando. La razón es que la cadena de reemplazo debe estar construida de tal manera que tenga en cuenta el nombre de cada grupo. Dado que se generan dinámicamente, esto no lo hace posible. En otras palabras, ¿cómo, en 1 afirmación, diseñas una cadena de reemplazo que cubriría c0 ... cn y sustituiría sus respectivos valores de captura? Podría recorrer los nombres, pero ¿cómo mantendría el texto modificado intacto para realizar 1 reemplazo por nombre de grupo?

Tengo una posible solución para usted. Todavía usa la sobrecarga de MatchEvaluator, pero con algunas expresiones lambda y LINQ puedes bajar esto a 1 línea. Sin embargo, lo formatearé para mayor claridad a continuación. Tal vez esto se ajuste a sus necesidades o lo encamine en la dirección correcta.

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

Salida:

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

¡Gracias! He resuelto mi problema de esa manera. Pero bajo el término "una línea" quise decir algo como Regex.Replace (fuente de cadena, patrón de cadena, " $ &"). Donde $ {groupName} es un reemplazo de nombre de grupo mítico (pero funciona cuando se conoce el nombre del grupo;). Pero parece que es imposible en mi caso. ¡Gracias por la respuesta! – Alex

Cuestiones relacionadas