Softwareontwikkeling FAQ: Regular expressionsMet dank aan Arien, tomato en Grum.InhoudsopgaveLinks
Boeken
Wat zijn reguliere expressies?Reguliere expressies zijn een manier om een (abstracte) taal te omschrijven. Je kunt zo aangeven welke woorden syntactisch correct zijn (en dus ook welke woorden dat niet zijn). Is het eerste dat in je opkomt nu ":?", vergeet dit dan. De onderstaande omschrijving voldoet prima.Reguliere expressies zijn een manier om strings te omschrijven. Hoe je een bepaalde regex schrijft hangt af van de taal of tool die je gebruikt, kijk dus in de docs. Ik gebruik in het vervolg Perl als voorbeeld. VoorbeeldLaten we eenvoudig beginnen en eerst een kijken hoe zo'n regex er dan in het wild uitziet.Stel, je wilt uit een bestand (waarin op elke regel een woord staat) de woorden halen waar een "a" in zit. Een stukje van de code zou zo kunnen zijn in Perl: Perl:
Wat er hier gebeurt is dat iedere keer een regel uit het bestand gelezen wordt (en de inhoud van die regel automagisch in de variabele $_ gekopieerd wordt). Vervolgens wordt gekeken of de regel (dat wil zeggen de waarde van de magische $_ variabele) voldoet aan de regex /a/, en als dat zo is wordt de regel (dat wil zeggen de waarde van de magische $_ variabele, die zo magisch is dat je hem niet eens ziet) geprint. Zoals je ziet matcht de "a" in de regex /a/ zichzelf. Dit geldt voor de meeste tekens. Hoe zou je kunnen kijken welke woorden "aa" (dus een "a" gevolgd door nog een "a") bevatten? Denk eerst even na... Inderdaad, met de regex /aa/. Het achter elkaar zetten van tekens in een regex heeft tot gevolg dat de tekens in volgorde gematcht moeten worden. Nou zei ik boven dat de meeste tekens zichzelf matchen, maar wat doen die andere tekens dan? Die andere tekens (metacharacters) zorgen ervoor dat er iets speciaals gebeurt, ze geven bijvoorbeeld een keuze of een herhaling aan. Als een teken speciaal is kun je het zo speciaal maken dat het weer normaal wordt (dus: zichzelf matcht) door er een backslash voor te zetten. Op dezelfde manier kun je een normaal teken speciaal maken (zie hieronder). KeuzesWat nu als je wilt kijken of een regel "aa" of "ee" bevat? Voor keuzes kun je het pipe symbool op de volgende manier gebruiken:Perl:
HerhalingOm aan te geven dat een bepaald teken een aantal keer herhaald moet/mag worden kun je de volgende constructies gebruiken:Perl:
Uit zichzelf zal de regex engine proberen zo vaak mogelijk te matchen als het de keuze krijgt tussen minder of meer matchen op dezelfde plek. Dus (match in vierkante haken): Perl:
Je ziet dat /a+/ zo vaak mogelijk een "a" match. Of is dat niet zo? Verder naar recht staan meer"a"s dan hij er nu pakt! Het belangrijke punt om te onthouden is dat een regex van links naar rechts werkt en houdt van "instant gratification" (als hij nu kan zorgen voor een complete match, waarom dan nog verder gaan? maar ook: als hij nu veel kan pakken in plaats van weinig, waarom dan met weinig tevreden zijn?). Lees het stukje hierboven nog eens en let op het vetgedrukte "op dezelfde plek". GroupingOm stukken van een regex te groeperen gebruik je haakjes, bijvoorbeeld:Perl:
AssertionsSoms wil je niet een bepaald teken matchen, maar wil je alleen kijken of iets waar is of niet.Om aan te geven waar je wilt dat de match moet zijn kan je anchors gebruiken: Perl:
De ^ zorgt er dus voor dat de match alleen slaagt als ^ kan matchen aan het begin van de string. ^ neemt geen ruimte in! (Idem voor $). Ook kan je kijken of je op de grens van een "woord" bent (een "woord" bestaat in Perl uit letters, cijfer en de underscore, tenzij je met Unicode bezig bent) of juist niet: Perl:
Character classesAls kortere notatie voor keuzes tussen karakters kun je character classes gebruiken. Bijvoorbeeld om een teken te matchen dat een "a", een "b" of een "c" kan zijn kan beide onderstaande constructies gebruiken:Perl:
Een character class is een opsomming van tekens, en binnen de character class (dus tussen de begin [ en de eind ] verliezen metacharacters als |, (, ), en . (waar ik het zo over heb) hun speciale betekenis. Perl:
Om binnen een character class een "-" te gebruiken kan je hem aan het begin (direct na de openingshaak), aan het einde van de class zetten of escapen: Perl:
Kijk eens of je in de docs van jouw taal of tool kunt vinden hoe je een letterlijke "[" of "]" in een character class op kunt nemen. |
[ Voor 32% gewijzigd door NMe op 21-12-2019 18:16 ]
'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.