2009-01-23 9 views
1

Je commence à peine à utiliser Regex donc je respecte ma terminologie. J'ai un motif regex qui fonctionne correctement sur une chaîne. La chaîne pourrait être au format "text [pattern] text". Par conséquent, j'ai aussi un motif regex qui annule le premier motif. Si j'imprime les résultats de chacun des matches, tout est affiché correctement.Utilisation de Regex pour modifier une chaîne en C#

Le problème que je vais avoir est que je veux ajouter du texte dans la chaîne et il modifie l'indice des matches dans un MatchCollection regex. Par exemple, si je voulais joindre le match trouvé dans « td » match «/td » » balises je le code suivant:

Regex r = new Regex(negRegexPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); 
      MatchCollection mc = r.Matches(text); 
      if (mc.Count > 0) 
      { 
       for (int i = 0; i < mc.Count; i++) 
       { 
        text = text.Remove(mc[i].Index, mc[i].Length); 
        text = text.Insert(mc[i].Index, "<td>" + mc[i].Value + "</td>"); 
       }     
      } 

Cela fonctionne très bien pour le premier match mais comme on pouvait s'y attendre le. mc [i] .Index n'est plus valide parce que la chaîne a changé.Par conséquent, j'ai essayé de rechercher juste une seule correspondance dans la boucle for pour le nombre de correspondances que je m'attendrais (mc.Count), mais je continue à trouver le premier match.

Alors je l'espère sans introduire plus regex pour vous assurer qu'il n'est pas le premier match et garder tout dans une chaîne, que quelqu'un a une entrée sur la façon dont je pourrais y arriver? Merci pour vos commentaires.

Edit: Merci à tous pour vos réponses, je les apprécie tous.

+0

Juste un petit commentaire. Vous n'avez pas besoin du bloc if (mc.Count> 0). S'il n'y a aucun élément dans la collection, il n'entre pas dans la boucle for de toute façon. – BFree

+0

Un exemple de chaîne de ce que vous avez réellement, et ce que vous voulez avoir pourrait être utile. J'ai le sentiment pas si injustifié que regex est le mauvais outil pour votre tâche. – Tomalak

Répondre

3

Il peut être aussi simple que: -

string newString = Regex.Replace("abc", "b", "<td>${0}</td>"); 

Résultats dans a<td>b</td>c.

Dans votre cas: -

Regex r = new Regex(negRegexPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); 
text = r.Replace(text, "<td>${0}</td>"); 

remplacera toutes les occurance de negRegexPattern avec le contenu de ce match entouré par l'élément td.

+0

Une telle solution simple et élégante, merci! – Sean

-2

Conservez un compteur avant le début de la boucle et ajoutez la quantité de caractères que vous avez insérée à chaque fois. IE:

  Regex r = new Regex(negRegexPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); 
      MatchCollection mc = r.Matches(text); 

       int counter = 0; 
       for (int i = 0; i < mc.Count; i++) 
       { 
        text = text.Remove(mc[i].Index + counter, mc[i].Length); 
        text = text.Insert(mc[i].Index + counter, "<td>" + mc[i].Value + "</td>"); 
        counter += ("<td>" + "</td>").Length; 
       } 

Je n'ai pas testé cela, mais cela DEVRAIT fonctionner.

1
static string Tabulate(Match m) 
    { 
     return "<td>" + m.ToString() + "</td>"; 
    } 

    static void Replace() 
    { 
     string text = "your text"; 
     string result = Regex.Replace(text, "your_regexp", new MatchEvaluator(Tabulate)); 
    } 
+0

mieux d'ajouter une sorte d'explication avec le code ... – annakata

2

Bien que je suis d'accord que la réponse ci-dessus Regex.Replace est le meilleur choix, pour répondre à la question que vous avez posée, que diriez-vous de remplacer du dernier match au premier. De cette façon, votre chaîne se développe au-delà de la correspondance "précédente" de sorte que les index des correspondances antérieures seront toujours valides.

for (int i = mc.Count - 1; i > 0; --i) 
1

Vous pouvez essayer quelque chose comme ceci:

Regex.Replace(input, pattern, match => 
{ 
    return "<tr>" + match.Value + "</tr>"; 
}); 
Questions connexes