webdesign, reguliere expressies
Soms kom je zoiets als dit tegen :
s/(^[A_Z]{1})([a-z]+)\.sgml/\1\2\.html/g
tr/a-z/A-Z/
(slik)… Het is een zogenaamde regular expression. WAT ?
Stel je zit in Word en wilt overal waar je “hallo” getypt hebt dit vervangen door “hoi”. Dat is vrij simpel en je doet dit door in het menu “zoeken en vervangen” te kiezen. Soms is e.e.a. wat lastiger : stel je hebt 500 Word bestanden en je wilt overal waar je een html bestand hebt aangegeven “Bla.html”, die begint met een hoofdletter en begint op het begin van de regel vervangen door “bla.sgml” (alle letters naar kleine letters en de extensie vervangen van .html naar .sgml), wat dan?
Met regular expressions kun je meest wilde trucs uithalen op tekst. Je kunt zoeken en vervangen maar bijvoorbeeld ook alle mail die bepaalde tekst bevat automatisch en snel aanduiden als spam.
Kleene
Regular Expressions zijn bedacht door de Amerikaanse wiskundige Stephen Kleene, deze bedacht deze in het kader van “de algebra van reguliere sets”.
Het “*” wat velen van jullie wel kennen als “wildcard” heette origineel dan ook de “Kleene Star”. De “*” staat over “alles”.
patroon
In regular expressions is alles een patroon, wanneer je zoekt naar “hallo” dan zoek je in feite naar een patroon dat opgebouwd is uit de tekens h-a-l-l-o.
zoek en vervang
Zoeken en vervangen gaat eenvoudig met regular expressions. Stel je wilt “hallo” vervangen door “hoi”. Je schrijft dan :
s/hallo/hoi/g
De ’s’ staat dan voor ’substitute’ en dit betekent in het nederlands ‘vervang’. De ‘g’ staat voor ‘global’ en betekent doe het overal waar je ‘hallo’ tegenkomt op een regel.
metakarakters
Metakarakters kunnen binnen regular expression gebruikt worden als tekens die je op meerdere manieren kunt opvatten of die meerdere sets van tekens beschrijven. Een voorbeeld doet wonderen :
. (de punt) betekent : match elk karakter inclusief de spatie
[…] (de vierkante haken) betekent : match elk karakter tussen de haken
[^…] (met een tot-de-macht teken) betekent : elke karakter behalve degene
tussen te haken
[N-M] betekent : match elk karakter in de range N-M
Een voorbeeld doet wonderen :
hallo[0123456789] matcht op bijvoorbeeld “hallo1″, “hallo2″, “hallo3″
hallo[0-9] doet exact hetzelfde !
hallo[0-9a-zA-Z] matcht op “hallo” gevolgd door elk willekeurig numeriek of
alfanumeriek teken
hallo[0-9 a-z A-Z] is wellicht wat beter leesbaarder maar doet iets heel
anders : deze matcht ook op een spatie !!
h.*o matcht alles wat begint met een ‘h’ en eindigt op ‘o’
macro’s
Vaak kun je macro’s gebruiken voor je regular expression. In perl kun je bijvoorbeeld aangeven : \d i.p.v. [0-9] en \w i.p.v. [a-zA-Z0-9_].
quantifiers
Naast voorgaande zaken is het soms handig als je kunt aangeven hoe vaak een bepaalde template moet voorkomen. Daarvoor kun je zogenaamde quantifiers gebruiken :
? : match het voorgaande karakter 0 of 1 keer
* : match het voorgaande karakter 0 of meerdere keren
+ : match het voorgaande 1 of meerdere keren
{N} : match het voorgaande N keren
{min,max} : match het voorgaande tussen min of max keren
Een voorbeeld doet wonderen :
ha[l]+o vindt o.a. het volgende : “halo”, “hallo”, “halllllo” en
“halllllllo”. M.a.w. de “l” mag er 1 of meedere keren inzitten.
hallo[0-9]{3} matcht met “hallo123″, “hallo999″ maar niet met “hallo1000″
anchors
Vaak wil je ook aangeven op welke positie iets begint. Je geeft dit aan door middel van zogenaamde anchors.
^ : match op het begin van de regel
$ : match op het einde van de regel
\ : match op het einde van een woord
\b : match op het begin of het einde van een woord
\B : match elke karakter dat niet aan het begin OF aan het einde van een woord
staat
escape characters
Wat als je nou wilt zoeken op een ‘+’ ?? Dit is immers een quantifier. Welnu dan gebruik een een escape character. Dit is niets meer dan het plaasen van
een ‘\’ voor dat teken.
alternatieven
Soms wil je iets aanduiden met een “of” operator : zoek naar “hoi” of “hallo”", dit doe je met een “|”. Bijvoorbeeld :
/(hoi|hallo|dag)/
Let erop dat er geen spaties tussen staan !
backreferences
Soms wil je delen van wat je matcht even onthouden in een zogenaamde “buffer”. Met regular expressions kun je dit aangeven door achter de “/” van de
expressie een nummer te plaatsen van de buffer. De hoeveelheid buffersnummers ligt tussen de 9 en onbeperkt (in perl).
Stel je voor je wilt alle aanroepen naar foo(a,b,c) vervangen door foo(c,b,a) je kunt dit doen door :
s/foo(\([^,]*\),\([^,]*\),\([^)]*\))/foo(\2,\1,\3)/g
modifiers
Modifiers plaats je achter je “/” en daarmee kun je bepaalde generieke modificaties aangeven op je patroon.
i : hou geen rekening met hoofdletters of kleine letters
m : behandel de string als meerdere regels
s : behandel de string als 1 regel
x : hou geen rekening met spaties
bijvoorbeeld : /jip|janneke/xsi
groepering karakters
Nog een maal de groepering karakters ter verduidelijking :
() : groepeert een groep
[] : groepert een karakter bereik
{} : groepert een herhalings opgave
meer voorbeelden
/h…l/ : matcht alles met een “h” gevolgd door 3 karakters gevolgd door een
“l”
/([0-9]{4}([- ])*){3}[0-9]{4}/ : matcht een nummer bestaande uit 16 nummers gegroepeerd in 4 delen gescheiden door optionele “-” of ” “.
s/ */ /g : verander een of meer spaties in een enkele spatie
s/ *$/ /g : haal alle spaties aan het einde van een regel weg
s/^/ /g : voeg een spatie toe aan het begin van elke regel
s/^[0-9][0-9]* //g : haal alle nummers aan het begin van elke regel weg
s/b[aeio]g/bug/g : vervang bag door bug, beg door bug, big door bug
s/t\([aou]\)g/h\1t/g : vervang alle tag,tog,tug door hat,hot en hug
^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$
dit matcht alle e-mail adressen volgende specs ( hoezo e-mail validatie)
^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$
matcht 99% van alle e-mail adressen
^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$
matcht het formaat van ip adressen( werkt perfect met het asp.net
regularexpressions validator control
(^\+[0-9]{2}|^\+[0-9]{2}\(0\)|^\(\+[0-9]{2}\)\(0\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\-\s]{10}$)
matcht nederlandse telefoonnumers (hoezo validatie routine?)
^[0-9]{4}\s{0,1}[a-zA-Z]{2}$
matcht nederlandse postcode
en dan nog…
Er bestaan vele implementaties van regular expressions. Elke pakket, text-editor of programmeertaal heeft wel weer verschillen. Daarnaast betekenen vaak tekens weer iets anders als ze op een andere plaats staan.
Leuke linkjes :
* opengroup
* tao of regular expressions
* in php
* een database van veel voorkomende regular expressions
en natuurlijk Google…