Comme les autres ont dit, vous voulez faire une boucle sur Match
es pas plus Group
s que votre modèle a un seul groupe. La manière habituelle de faire est soit la boucle de Michael Gunter for
ou tout simplement
Match m = reg.Match(line);
while(m.Success)
{
// read class from m.Groups[1]
m = m.NextMatch();
}
Cependant, pour résoudre votre problème ultime, obtenir toutes les données séparément et mettre la chaîne de retour ensemble pourrait être un peu ennuyeux - surtout si vous vouloir faire ce remplacement en plusieurs lignes à la fois. Par conséquent, vous voudrez peut-être regarder dans Regex.Replace
(la version prenant un rappel). De cette façon, vous pouvez faire correspondre tout dans une seule correspondance, puis utiliser la capacité unique de .NET pour accéder à plusieurs captures d'un seul groupe.
var line = "<!C43!><!TG!>Some Characters";
MatchEvaluator evaluator = new MatchEvaluator(ReplaceCallback);
string output = Regex.Replace(
line,
@"(?:<!([^<>]+)!>)+(.+)",
evaluator
);
Et ailleurs dans votre classe:
static string ReplaceCallback(Match match)
{
var sb = new StringBuilder("<span class=\"");
sb.Append(match.Groups[1].Captures[0].Value);
for(int i = 1; i < match.Groups[1].Captures.Count; i++)
{
sb.Append(" ");
sb.Append(match.Groups[1].Captures[i].Value);
}
sb.Append("\">");
sb.Append(match.Groups[2].Value);
sb.Append("</span>");
return sb.ToString();
}
Configuration de la chaîne est probablement plus facile avec String.Format
mais je ne pouvais pas trouver un moyen au moment de l'String.Join
CaptureCollection
.
Alors, que ce fait essentiellement:
Le motif @"(?:<!([^<>]+)!>)+(.+)"
correspond à un ou plusieurs <!...!>
« jetons », puis le reste de la ligne. Ce faisant, il capture le contenu du <!...!>
. À chaque répétition, une autre capture est enregistrée et vous pouvez y accéder plus tard dans le rappel. Après les jetons <!...!>
, nous correspondons et capturons le reste de la ligne avec (.+)
. Notez le @
devant la chaîne: il crée la chaîne verbatim, ce que vous devez toujours faire lorsque vous spécifiez des modèles regex - sinon vous aurez des problèmes quand il s'agit d'échapper. Notez également que ?:
après la première parenthèse ouvrante. C'est pour supprimer la capture, car nous n'avons pas besoin d'une autre capture qui contient les délimiteurs <!
et !>
. Toujours utiliser des groupes non-capturant, sauf si vous avez réellement besoin de capture est également une bonne pratique.
La fonction de rappel est ensuite appelée pour chaque correspondance dans l'entrée. Il n'y a qu'une seule correspondance qui contient la ligne entière. Ce match a capturé deux jetons dans le groupe 1
et le reste de la ligne dans le groupe 2
.
Ainsi, nous pouvons maintenant construire simplement une chaîne, qui commence par <span ="
, puis une liste limitée de toutes les captures du groupe 1
, puis ">
, puis le reste de la ligne capturé et enfin la fermeture </span>
.
Comme je l'ai dit, si vous trouvez un moyen de String.Join
le groupe de collecte, la fonction de rappel réduit à trois lignes ou plus.
Si la distinction entre Match
, Group
et Capture
est encore un peu floue pour vous, je vous suggère de mettre un point d'arrêt dans la fonction de rappel et juste d'examiner l'objet il match
.
wow, réponse parfaite, votre code a fonctionné comme un régal! Je vous remercie! :-) – Nnoel