Inleiding Reguliere Expressies
1. Inleiding
2. Metacharacters
• Character classes
• Parentheses
• Back references
• Begin en eind
• Quantifiers
3. Alles op een rijtje
4. Oefenen
5. Slot
1. Inleiding
Hoi en welkom bij mijn eerste tutorial. Ik hoop dat ik een goede tutorial heb geschreven.
Ik zal niet veel zeggen, behalve dat reguliere expressies niet iets is wat je even in 10 minuten kunt leren.
Ikzelf, op dit moment, heb nog niet alles van reguliere expressies geleerd. Maar dat is genoeg
om jullie een en ander te leren. Als je iets ziet dat helemaal niet klopt, pm me maar of post een reactie.
Goed, aan de slag dan maar?
PS: Ik zal wel de engelse namen gebruiken
top
2. Metacharacters
2.1 Character classen
Je hebt in de vorige paragraaf gezien wat een character class kan doen. Hij kan een range aangeven.
Dit is zeer belangrijk, en handig. Als deze handige functie niet bestond zou de regex van de vorige paragraaf er zo uitzien:
^[ABCDEFGHIJKLMNOPQRSTUVWXYZ]
Niet erg overzichtelijk he? Kijk eens goed naar hierboven; het streepje is weg! Dat is ook een metacharacter, eentje dat een
range aangeeft. Dit werkt voor letters en cijfers. [a-z] of [A-Z] of [0-9]. Merk ook op dat reguliere
expressies case sensitive zijn behalve als je die functie uitschakelt (maar dat is voor een andere keer ;-).
Het streepje werkt niet als hij helemaal vooraan staat, want dan weet de regex-engine wel dat er onmogelijk een range kan zijn.
En je hoeft niet per se bijv. a-z te gebruiken: a-f werkt ook ;-).
Als je gewoon tekens plaatst in een character class dan betekent dat niet een reeks tekens matchen, maar betekent dat:
match teken1 of teken2 of teken3 enzovoorts. Met andere woorden, er word de script operator
OR tussen elke teken in de class gezet.
[abcdefgh]
Dit ziet de regex-engine dus:
Match een a of een b of een c of een d of een
e of een g of een h.
Als je sommige metacharacters plaatst in een character class, krijgen ze een heel andere betekenis. Alsof binnen een character
class een eigen regex taaltje heerst. Een voorbeeld.
^[^a-z]
Dit is wat de regex engine verwerkt:
Match de begin van een lijn meteen gevolgd door EEN teken behalve een teken tussen de a en z
.
Zoals je ziet, betekent de 'hoedje' binnen een character class: alles matchen behalve wat er achter me staat.
top
2.2 Parentheses
Dit is ook een handige functie in de regex wereld. Je kunt met parentheses backreferences (zie §2.2.1) gebruiken.
Ook kun je aantal tekens waartussen een "OR" moet staan uitbreiden. Ook kun je lookarounds gebruiken, en nog een paar andere
dingen, maar dat valt buiten "De inleiding in Reguliere Expressies" ;-).
Laten we eens kijken naar de "OR" functionaliteit.
Omdat regex-engines niet echt kunnen raden waar je een OR tussen wilt plaatsen (want meerdere tekens zijn toegestaan), is er
een metacharater gemaakt die de OR functie mogelijk maakt in een parenthese, namelijk ⇒ |.
Deze 'pipe' kun je gebruiken om een OR te plaatsen tussen de woorden. Ik ga een voorbeeld gebruiken die ik op een website heb
gelezen, maar weet niet of ik de site mag opnoemen. Dus als iemand ripper gaat roepen dan weet die alvast dat ik dit niet
geript heb, maar geleend om jullie iets te leren :).
Er bestaan verschillende mogelijkheden om regular expressions te schrijven. Zo is er regex, regular expressions, regexes. Er zijn
misschien meer, maar dan word het wat onoverzichtelijk in de regex om het te begrijpen. Wij willen ze allemaal kunnen matchen.
We maken dan gebruik van de 'pipe' en parentheses en een functie in php die ik later pas zal uitleggen (in §2.4).
De regex word dan (ik ga ervan uit dat case-sensitivity uit staat):
reg(ex(es)?|ular expressions)
Dit is wat de regex-engine verwerkt:
Match reg meteen gevolgd door óf ex (met optioneel
es erachter) óf
ular expressions
Zie je dat de regex-engine niet leest: reg gevolgd door een e of een x
enzovoorts.
Zie je dat hij de hele woorden neemt en niet, zoals in een character class, ze in stukjes hakt.
top
2.2.1 Back references
Je kunt met parentheses ook back references maken. Een back reference is een verwijzing naar een parenthese. Ze worden
genummerd van links naar rechts. Dus de eerste parenthese krijgt referentie nummer 1 en de 2 e krijgt dus referentie
nummer 2 enzovoorts. Ik dacht ergens gelezen te hebben dat er een limiet op referenties zijn, maar daar hoef jij je geen zorgen
over te maken of je moet een zeer lange regex hebben met heel veel parentheses. Ik kan uitleggen hoe een backreferentie eruit
ziet, maar een voorbeeld is wel zo praktisch. Een voorbeeld dat veel mensen kennen die met een template parser hebben gewerkt.
Ik gebruikte deze regex vroeger om gegevens uit een TPL block te halen:
<!-- START BLOCK : (.*?) -->(.*?) <!-- END BLOCK : (.*?) -->
Nu kun je hem zo gebruiken:
<!-- START BLOCK : (.*?) -->(.*?)<!-- END BLOCK : 1 -->
Zoals je ziet, gebruik ik in plaats van (.*?) nu 1. Een backreference kun je met
slash () of dollar teken($) + referentie nummer aanroepen. Zo word je regex korter, en hoef je geen zorgen te maken
dat je een tikfout hebt gemaakt bij de 2e parenthese.
Wil je van een parenthese geen backreference maken, dan moet je '?:' net achter de '('
zetten.
top
2.3 Begin en eind
Wat bedoel ik met "Begin en Eind", vraag je jezelf zeker af ? Ik bedoel daarmee: metacharacters die de begin en eind van een
line kunnen matchen. Wat heb je hieraan, vraag je nogmaals ? Nou, dit is belangrijk bij bijvoorbeeld een e-mail adres
controleren bij het registreren. Je wilt niet dat in de inputveld een hele boek word gezet (hoewel dit toch niet kan :p) en
erachter de email adres. Want zonder de metacharacters van deze paragraaf, is dat mogelijk!
Ik heb het over het 'hoedje' ⇒ ^ EN de 'dollar teken' ⇒ $.
Het hoedje en de dollar teken matchen, respectievelijk, begin en eind.
^[A-Z][a-z]+.$
En de regex-engine leest het zo:
Match begin van lijn direct gevolgd door een teken tussen a en z (minstens 1x, meerdere
tekens zijn optioneel) direct gevolgd door een punt direct gevolgd door einde van lijn
Deze simpele regex matcht dus een zin (hoewel er op een lijn meerdere zinnen kunnen voorkomen, leestekens buiten beschouwing
zijn gehouden enzovoorts. Dit is voldoende voor de beginner, anders wordt het te moeilijk. ;-)).
top
2.4 Quantifiers
Welkom bij een makkelijke gedeelte van de 'regex-taal'. Quantifiers betekent letterlijk: "hoeveelheidsbepaler". Dit is een
redelijke beschrijving van deze functie in reguliere expressies. Ze bepalen hoeveel van iets moet komen. Je kunt kiezen om de
functies * + ? te gebruiken of een ander functie te gebruiken (de accolades). Ik begin met de */+/?, dan kom
ik wel terug op de accolades.
*
teken voor mij 0 of meerdere keren matchen
+
teken voor mij 1 of meerdere keren matchen
?
teken voor mij 0 of 1 keer matchen oftewel: teken voor mij is optioneel
Je kunt de hierboven genoemde quantifiers ook vervangen door de functies { en } te
gebruiken:
De */+/? quantifiers staan vast, maar de cijfers tussen de accolades niet. Regel voor accolades is dus:
{min,max}
Laat je de min of max weg (allebei kan niet!), dan komt oneindig in de plaats ervan.
top
3. Alles op een rijtje
In deze paragraaf gaan we alles herhalen :) Wat hebben we allemaal geleerd? Even een opsomming:
- Metacharacters
- De tekens in reguliere expressies die een betekenis hebben
- ^teken(s) betekent: match een begin van een lijn meteen gevolgd door teken(s)
- teken(s)$ betekent: match teken(s) meteen gevolgd door de einde van een lijn.
- Metacharacters kun je gebruiken als normale tekens
- Maar je moet ze wel escapen.
- Voor de metacharacter dat je wilt escapen, zet je een backslash neer
- Dit heb ik niet behandeld, omdat het zo simpel is
- Character classen
- De rechthoekige haakjes [ ]
- Tussen alle tekens binnen een character class is een denkbeeldige OR operator
- Je kunt ook een range gebruiken
- Dat doe je door een streep tussen 2 letters/cijfers te zetten
- Bijvoorbeeld: [a-z] of [0-9] of [A-Z] of [a-h] enzovoorts
- Een 'hoedje' => ^ binnen een character class heeft een andere betekenis
- [^teken(s)]
- Match elke teken behalve wat achter me staat
- Parentheses
- De ronde haakjes ( )
- De "pipe" => | is een OR, dus kun je meerdere tekens naast elkaar zetten
- Je kunt back referenties gebruiken
- Een backreference is alles tussen ( en )
- Backreferenties roep je aan met een slash of dollar teken ( OF $)
- Wil je een parenthese dat geen back reference is
- Zet dit meteen na de openingshaakje: ?:
- Quantifiers
- * betekent teken voor mij 0 of meerdere keren herhalen
- + betekent teken voor mij 1 of meerdere keren herhalen
- ? betekent 2 dingen:
- teken voor mij 0 of 1 keer matchen
- teken voor mij is optioneel
- Je kunt je eigen quantifier maken met accolades
- {min, max}
- laat je min of max weg
- Lege plek betekenis: oneindig
top
4. Oefenen
Een tutorial is niet compleet zonder een paar oefeningen, vind ik tenminste :) Dus hieronder heb ik een paar (moeilijke[?])
oefeningen neergezet voor je. Als het je gelukt is om er eentje goed te hebben, mail ze dan naar mij. Ik wil wel zien wat mijn
"leerlingen" van deze tutorial hebben geleerd :)
1. Maak een email regex (en niet stiekem in de script library bekijken)
2. Maak een regex dat een HTML pagina kan matchen, die valid is.
Dus bij niet valid pagina's => geen match
3. Maak een regex dat internet adressen matcht.
4. Van een boek: Maak een regex dat de tijd kan matchen (hh:mm) en hij moet uur in 2 modes matchen: 12 (met am/pm dus) en 24 (dus t/m 00:00 (12 uur 's nachts)).
top
5. Slot
We zijn aangekomen bij de afscheid. Maar we zeggen geen vaarwel, maar tot ziens. Er is nog veel te vertellen over reguliere
expressies die ik nog niet heb besproken in deze tutorial. Er zal binnenkort nog een tutorial verschijnen van mijn hand, reken
daar maar op ;-). En antwoorden op de vragen hierboven kun je mailen naar mij via mijn profiel :) (ik heb het niet zo op spam
mail, anders zette ik me mail hier neer).
top
|