2009-07-08 6 views
5

Il existe une méthodeRegex: Les groupes nommés et remplacements

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

Le dernier paramètre prend en charge le remplacement des motifs tels que ${groupName} et d'autres (mais je ne sais pas le nom du groupe dans le temps d'exécution).

Dans mon cas, je le modèle créé dynamiquement comme:

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

Mon but est de remplacer chaque groupe avec la valeur selon le nom du groupe. Par exemple, le mot "word1" sera remplacé par <span class="c0">word1</span>. Ceci est pour les résultats de recherche mettant en évidence comme google.

Est-il possible de le faire en utilisant la méthode ci-dessus sans utiliser la méthode surchargée avec le paramètre MatchEvaluator?

Merci d'avance!

+0

Je viens d'aller avec MatchEvaluator ... ça marche ... –

+0

Eh oui, merci! En fait, j'ai une solution de travail avec MatchEvaluator. Mais comment élégant serait une solution avec une seule ligne de code au lieu de six-sept :) – Alex

Répondre

3

Je ne pense pas que l'utilisation de $ {groupname} de la manière que vous avez suggérée est faisable à moins que je ne comprenne pas le remplacement exact qui est en train d'être effectué. La raison est que la chaîne de remplacement doit être construite de telle sorte qu'elle représente chaque nom de groupe. Comme ils sont générés dynamiquement, cela ne le rend pas possible. En d'autres termes, comment, dans une déclaration, concevez-vous une chaîne de remplacement qui couvrirait c0 ... cn et remplacerait leurs valeurs de capture respectives? Vous pouvez faire défiler les noms, mais comment conserver le texte modifié intact pour effectuer 1 remplacement par nom de groupe?

J'ai cependant une solution possible pour vous. Il utilise toujours la surcharge MatchEvaluator, mais avec certaines expressions lambda et LINQ, vous pouvez réduire cette valeur à 1 ligne. Cependant, je vais le formater pour plus de clarté ci-dessous. Peut-être que cela correspond à vos besoins ou vous orienter dans la bonne direction.

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

Sortie:

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

Merci! J'ai résolu mon problème de cette manière. Mais sous le terme "une ligne" je voulais dire quelque chose comme Regex.Replace (chaîne de caractères, modèle de chaîne, " $ &"). Où $ {groupName} est un remplacement de nom de groupe mythique (mais cela fonctionne quand le nom du groupe est connu;). Mais il semble que ce soit impossible dans mon cas. Encore un merci pour la réponse! – Alex

Questions connexes