TOC

This article has been localized into Dutch by the community.

Reguliere Expressies (Regex):

Zoeken met de Regex class

Zoals we in het vorige hoofdstuk bespraken, kun je met Regular Expressions zoekpatronen definiëren voor het werken met strings. Voor het verwerken van dit zoekpatroon, komt het .NET framework met een zeer veelzijdige class: de Regex class. In dit artikel zullen we een aantal zoekpatronen definiëren en die gebruiken met de Regex class. Denk er echter alsjeblieft aan dat de syntaxis van Regular Expressions behoorlijk gecompliceerd kan zijn en dat dit een C# tutorial is en geen Regex tutorial. Toch zal ik een paar eenvoudige Regex patronen gebruiken om te demonstreren hoe je er in C# mee kunt werken. Als je meer wilt weten over Regular Expressions kan ik dit recommanderen: Regular Expression Tutorial.

De IsMatch Method

In dit eerste voorbeeld zal ik één van de meest basale methods van de Regex class gebruiken, genaamd IsMatch. Hij retourneert alleen maar true of false, afhankelijk van of er één of meerder 'matches' gevonden worden in de test string:

string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
if (regex.IsMatch(testString))
    Console.WriteLine("String contains numbers!");
else
    Console.WriteLine("String does NOT contain numbers!");

We definiëren een test string en daarna creëren we een exemplaar van de Regex class. We voeren in de huidige Regular Expression een string in, in dit geval, en de regex specificeert dat we naar een getal van ongeacht wat voor lengte zoeken. Daarna 'outputten' we een tekstregel, afhankelijk van of de regex een 'match' is voor onze test string. Heel fraai, maar in de meeste gevallen wil je iets doen met de 'match(es)', en hiervoor hebben de Match class>

De Match Class & Method

In dit volgende voorbeeld leggen we het gevonden getal uit de test string vast en tonen het aan de gebruiker, in plaats van alleen maar te verifiëren dat het er is:

string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Number found: " + match.Value);

We gebruiken dezelfde regex en test string als zopas. Ik roep de Match() method aan, die een exemplaar van de Match class zal retourneren, dit gebeurt zowiezo of er nu wel of geen match wordt gevonden. Om er zeker van te zijn dat een match is gevonden, check ik de Success property. Als ik er zeker van ben dat een match is gevonden, gebruik ik de Value property om hem op te halen.

De match class bevat meer nuttige info dan alleen maar de gematchte string, bv. kun je zomaar uitzoeken waar de match werd gevonden en hoe lang hij is, enzovoorts:

string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Match found at index " + match.Index + ". Length: " + match.Length);

De Index en Length properties worden hier gebruikt om informatie te tonen over de locatie en de lengte van de 'match'.

Capture Groepen

In de eerste paar voorbeelden vonden we maar een enkele waarde in onze zoekstring, maar Regular Expressions kan natuurlijk veel meer doen dan dat! We kunnen bijvoorbeeld zowel naam als leeftijd in onze teststring vinden, terwijl we irrelevant spul zoals de command en de 'years' tekst eruit gooien. Iets dergelijks is een 'eitje' voor Regular Expressions, maar als je niet bekend bent met de syntaxis lijkt het erg gecompliceerd. Laten we er toch maar een poging aan wagen:

string testString = "John Doe, 42 years";
Regex regex = new Regex(@"^([^,]+),\s([0-9]+)");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Name: " + match.Groups[1].Value + ". Age: " + match.Groups[2].Value);

Ik heb de gemodificeerde regex zo veranderd dat hij naar alles zoekt wat GEEN komma is. Deze waarde is geplaatst in de eerste 'capture' groep, dankzij de omringende ronde haken. Daarna zoekt hij naar de scheidingskomma en daarna naar een getal, dat in de tweede 'capture' groep is geplaatst (alweer dankzij de ronde haken). In de laatste regel gebruik ik de Groups property om toegang te krijgen tot de gematchte groepen. Ik gebruik index 1 voor de naam en 2 voor de leeftijd omdat het de volgorde gebruikt waarin de match groepen werden gedefinieerd in de regex string (index 0 bevat de gehele match).

Capture Groups met Naam

Zodra de regex meer gevorderd/langer is dan die we zojuist gebruikt hebben, kunnen genummerde 'capture groups' onhanteerbaar worden omdat je je voortdurend de volgorde en de index ervan moet herinneren. Gelukkig voor ons ondersteunt Regular Expressions en het .NET framework 'capture groups' met een naam, waardoor je elke groep in de regex een naam kan geven en er daarna aan kunt refereren in de Groups property. Bekijk dit herschreven voorbeeld waar we groepsnamen gebruiken in plaats van nummers:

string testString = "John Doe, 42 years";
Regex regex = new Regex(@"^(?<name>[^,]+),\s(?<age>[0-9]+)");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Name: " + match.Groups["name"].Value + ". Age: " + match.Groups["age"].Value);

Het gaat precies zoals eerst, maar nu kun je logische namen gebruiken om de gematchte waarden op te zoeken in plaats van de juiste index te moeten onthouden. Dit is weliswaar geen groot verschil in ons simpele voorbeeld, maar, zoals gezegd, zul je het gaan appreciëren wanneer jouw Regular Expressions toeneemt in complexiteit en lengte

De MatchCollection Class

De Match class is hèt middel als je alleen maar met één enkele match wilt werken (denk eraan dat een match meerdere values kan bevatten, zoals we zagen in de vorige voorbeelden). Maar soms wil je met meerdere matches tegelijk werken. Hiervoor hebben we de Matches() method, die een MatchCollection class retourneert. Hij bevat alle gematchte waarden in de volgorde waarin ze werden gevonden. Laten we eens kijken hoe deze class te gebruiken is:

string testString = "123-456-789-0";
Regex regex = new Regex(@"([0-9]+)");
MatchCollection matchCollection = regex.Matches(testString);
foreach (Match match in matchCollection)
    Console.WriteLine("Number found at index " + match.Index + ": " + match.Value);

Ik heb de regex en de teststring veranderd, vergeleken met de voorgaande voorbeelden. We hebben nu een teststring met meerdere getallen en een regex die specifiek zoekt naar strings die uit één of meer getallen bestaan. We gebruiken de Matches() method om een MatchCollection van onze regex te krijgen, die de matches bevat die in de string werden gevonden. In dit geval zijn er vier matches die we na elkaar 'outputten' met een foreach loop. Het resultaat ziet er ongeveer zo uit:

Number found at index 0: 123
Number found at index 4: 456
Number found at index 8: 789
Number found at index 12: 0

Als er geen matches zouden worden gevonden, dan zou een lege MatchCollection worden geretourneerd.

Samenvatting

Met behulp van de Regex class, en samen met de Match en MatcgCollection classes, kunnen we strings op een heel geavanceerde manier matchen. De Regular Expression syntaxis kan erg gecompliceerd lijken, maar als je het eenmaal snapt dan heb je een zeer sterk hulpmiddel. Zelfs als je geen tijd wilt investeren in het leren van de regex syntaxis, kun je vaak voor specifieke behoeften via 'Google search' expressions vinden , die door andere programmeurs zijn gemaakt. Zodra je de regex string hebt geschreven of geleend, kun je hem voor je eigen doeleinden gaan gebruiken met de technieken en classes die we in dit artikel hebben gedemonstreerd.

Maar zoeken is maar een deel van de pret. Je kunt ook een paar heel interessante search/replace (zoek/vervang) operaties doen met Regular Expressions. Dit gaan we bekijken in één van de volgende artikelen.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!