This article has been localized into Dutch by the community.
Search/Replace met de Regex Class
In een vorig artikel hebben we de Regex class besproken en hoe we die kunnen gebruiken als we een string willen doorzoeken. Regular Expressions zijn hier prima geschikt voor, maar een ander gebruiksgeval doet zich voor als je search/replace operations wilt uitvoeren, waarbij je zoekt naar een specifiek patroon dat je door iets anders wilt vervangen. De String class heeft al een Replace() method, maar die is alleen maar geschikt voor simpele zoekopdrachten. Als je Regular Expressions gebruikt, kun je de kracht van regex zoekopdrachten gebruiken en zelfs 'captured' groepen gebruiken als onderdeel van de vervangende string. Klinkt dat gecompliceerd? Geen zorgen, we beginnen met een eenvoudig voorbeeld en werken dan gestadig door naar meer geavanceerde gevallen.
Zoals in het voorgaande artikel, gaan alle voorbeelden ervan uit dat je de RegularExpressions namespace hebt geimporteerd:
using System.Text.RegularExpressions;
Als dat gedaan is, gaan we werken aan stringvervanging via Regular Expressions. We zullen de Replace() method gebruiken die we vonden in de Regex class:
string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<[^>]+>");
string cleanString = regex.Replace(testString, "");
Console.WriteLine(cleanString);
Dit voorbeeld laat een gesimplificeerde benadering zien van het verwijderen van HTML tags bij een string. We matchen alles waar blokhaken ([ ]) omheen staan (<>) en gebruiken dan de Replace() method om elke voorval te vervangen met een lege string, wat vooral betekent het verwijderen van de HTML tags uit de teststring.
Vervanging met Gevangen Waarden (Captured Values)
Maar stel nu, dat je ze niet wil verwijderen, maar in plaats daarvan de tags wil veranderen in iets dat niet door de browser geïnterpreteerd zal worden, bv. door de punthaken (<>) te vervangen door vierkante haken ([ ] ) . Dit is precies waar de Regular Expressions hun ware kracht tonen, omdat het in feite heel gemakkelijk is, zoals geïllustreerd in deze lichtelijk herschreven versie van ons vorige voorbeeld:
string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<([^>]+)>");
string cleanString = regex.Replace(testString, "[$1]");
Console.WriteLine(cleanString);
Ik veranderde alleen maar twee minieme details: Ik voegde een paar ronde haken toe aan de regex om een 'capture' groep te maken, in wezen het 'capturen' van de waarde tussen de vierkante haken in de eerste 'capture' groep. In de Replace() method refereer ik hiernaar met gebruik van de speciale notatie $1,, dat in feite alleen maar betekent 'capture' groep nummer 1. Dit gedaan hebbende, ziet onze output er nu zo uit:
[b]Hello, [i]world[/i][/b]
Capture Groepen met Naam
Je kunt natuurlijk hetzelfde doen met 'capture' groepen die een naam hebben gekregen (besproken in het vorige artikel), op deze manier:
string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<(?<tagName>[^>]+)>");
string cleanString = regex.Replace(testString, "[${tagName}]");
Console.WriteLine(cleanString);
Als je 'capture' groepen met een naam gebruikt, neem dan alleen maar de ${name-of-capture-group} notatie.
Gebruik van een MatchEvaluator method
Maar als je nu nog meer controle wilt over hoe de waarde wordt vervangen? We kunnen hiervoor een MatchEvaluator parameter gebruiken. Dat is in feite niet meer dan een referentie (plaatsvervanger) naar een method die steeds wordt aangeroepen als een vervanging moet worden gemaakt. Hierdoor kun je de vervangingswaarde wijzigen voordat hij gebruikt wordt. Laten we bij het HTML tags voorbeeld blijven dat we al een paar keer hebben gebruikt. Deze keer echter bepalen we welke HTML tags worden gebruikt. Hier volgt het volledige voorbeeld:
using System;
using System.Text.RegularExpressions;
namespace RegexSearchReplaceMethod
{
class Program
{
static void Main(string[] args)
{
string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<(?<tagName>[^>]+)>");
string cleanString = regex.Replace(testString, ProcessHtmlTag);
Console.WriteLine(cleanString);
}
private static string ProcessHtmlTag(Match m)
{
string tagName = m.Groups["tagName"].Value;
string endTagPrefix = "";
if(tagName.StartsWith("/"))
{
endTagPrefix = "/";
tagName = tagName.Substring(1);
}
switch (tagName)
{
case "b":
tagName = "strong";
break;
case "i":
tagName = "em";
break;
}
return "<" + endTagPrefix + tagName.ToLower() + ">";
}
}
}
Het eerste deel van het voorbeeld ziet er precies zo uit als zojuist, maar in plaats van een vervangingsstring te leveren, maken we een referentie naar onze ProcessHtmlTag() method. Zoals genoemd, wordt deze method steeds opgeroepen als een vervanging ophanden is, met de Match in kwestie als parameter. Dit betekent dat we in onze MatchEvaluator method alle info over de match hebben, zodat we gepast kunnen handelen. In dit geval gebruiken we de gelegenheid om de tags meer semantisch te maken door de vetgedrukte (b) tag te vervangen door de strong tag en de schuingedrukt (i) tag met een nadruk (em) tag. Het maakt niet uit of de tag is veranderd of niet, we maken er 'lowercase' van.
Het is duidelijk dat een MatchEvaluator parameter erg veel kan, en dit is nog maar een eenvoudig voorbeeld van wat bereikt kan worden.
Samenvatting
Zoek/vervang (search/replace) operaties zijn tot veel in staat als je Regular Expressions gebruikt, en zelfs tot nog meer met de MatchEvaluator parameter. Hierdoor zijn de mogelijkheden om strings te manipuleren vrijwel eindfeloos.