Tutorials

Reguliere expressies

de lezer op weg helpen in de wereld van reguliere expressies

Pagina 1

Inleiding

Voor deze tutorial heb je het volgende programma nodig indien je een windows gebruiker bent:
http://analyser.oli.tudelft.nl/regex/egrep.exe

Voor deze tutorial heb je de volgende bestanden nodig:
http://analyser.oli.tudelft.nl/regex/nl/fruit.txt
http://analyser.oli.tudelft.nl/regex/nl/katten.txt

Hoewel er vele perl hackers en andere gebruikers van reguliere expressies zijn, blijft het aantal tutorials en handleidingen over reguliere expressies op het 'net opvallend laag. Omdat ik steeds relatief veel vragen over reguliere expressies tegenkom, en zie hoe anderen er mee worstelen, heb ik besloten om deze web pagina te schrijven. Hou er wel rekening mee dat deze tutorial nog niet af is.

1.1. Doel
Het doel van deze tutorial is om de lezer op weg te helpen in de wereld van reguliere expressies. De basisconcepten worden uitgelegd, en de grootste valkuilen worden behandeld.

1.2. Notatie
Alle reguliere expressies in deze tutorial worden weergegeven in een monospace lettertype op een lichtgrijze achtergrond met een donkergrijze omlijning. Om spaties in reguliere expressies beter zichtbaar te maken, geef ik deze weer met het •-symbool. Het eindresultaat ziet er dan zo uit: reguliere•expressie.

1.3. Voorbeelden en Oefeningen
De meeste voorbeelden en alle oefeningen zijn gedaan met GNU egrep. Windows gebruikers kunnen hier een win32 versie van GNU egrep downloaden, of van de (min of meer) officiële site. Als je geen GNU egrep op je UN*X doos hebt, kun je het met proberen met de implementatie die bij je gebruikte UN*X variant hoort; deze zou grotendeels compatible moeten zijn.

Als de directory waar egrep is geïnstalleerd (zoals /usr/bin of C:\windows\command) in de $PATH variabele (%PATH% in Windows) staat, zou je egrep moeten kunnen aanroepen door simpelweg in te tikken

$ egrep
Usage: egrep [OPTION]... PATTERN [FILE]...
Try `egrep --help' for more information.Hier stelt het dollarteken de prompt van de shell voor (vergelijkbaar met C:\> in Windows) en dient niet ingetypt te worden. Alle voorbeelden met een commandoregel-aanroep laten deze prompt zien. Deze wordt gevolgd door de tekst die daadwerkelijk ingetypt dient te worden, welke altijd vet gedrukt is. De overige regels laten de uitvoer van het commando zien.

In principe geef je egrep een reguliere expressie om te matchen, en de naam van een bestand. egrep probeert dan de regex te matchen tegen elke regel van het bestand. Een regel wordt alleen afgedrukt als het de regex matcht.

1.4. Copyright en Distributie
Deze reguliere expressie tutorial is Copyright © 2003 door Kars Meyboom.

Deze tutorial mag vrij worden herdrukt in elk medium, mits de inhoud niet gewijzigd wordt, in zijn geheel wordt weergegeven, en deze copyright-melding gehandhaafd wordt. Alle code-voorbeelden in deze tutorial worden hierbij vrijgegeven in het publieke domein (public domain).

Neem contact op met <[email protected]> voor meer informatie.
Pagina 2

Wat zijn het?

Een reguliere expressie, meestal afgekort tot "regex" of "regexp", beschrijft tekstpatronen. Stel dat je op zoek bent naar een stukje text dat begint met twee, drie of vier letters 'A', gevolgd door precies drie letters 'C'. Dit patroon kan beschreven worden met de regex A{2,4}C{3}.

Uit bovenstaande regex kun je afleiden dat niet alle karakters letterlijk geïnterpreteerd worden. De accolades (of snorretjes, kies maar) hebben duidelijk een speciale betekenis. Karakters met zo'n speciale betekenis worden metakarakters genoemd. Goed, reguliere expressies hebben dus hun eigen syntaxis, en daarom zou je kunnen spreken van een regex taal.

Net als met de meeste mensentalen heeft de regex-taal vele dialecten; regexes geschreven voor perl zijn niet automatisch ook geschikt voor sed, awk or grep, om maar paar standaard UNIX tools te noemen.

Ik heb ervoor gekozen om alle regexes in deze tutorial in het POSIX dialect te schrijven. Dit omdat POSIX langzaam terein aan het winnen is in de wereld van reguliere expressies, en omdat een flink aantal dialecten er erg veel op lijkt (nou ja, eigenlijk is het andersom). Dit betekent echter niet dat ik alle features van de POSIX 1003.2 reguliere expressie standaard behandel. Een andere reden waarom ik het POSIX dialect gebruik in plaats het Perl dialect is omdat de Perl documentatie het Perl dialect veel beter uitlegt dan ik ooit zal kunnen. Bovendien, op deze manier zit je niet vast aan de extensies van een bepaalde tool. Je zou kunnen zeggen dat het POSIX dialect een soort van grootste gemene deler is.

2.1. Gebruik
Een regex op zich doet vrij weinig. Pas waneer zo'n beshrijving van een tekstpatroon wordt toegepast op een stuk tekst, gebeurt er wat. Het toepassen wordt gedaan door een stukje software dat de regex engine (motor) wordt genoemd. De tekst wordt vanaf het begin doorzocht tot een stuk tekst is gevonden dat aan de beschrijving van het patroon (de regex) voldoet, of tot de tekst op is. Als er inderdaad een stuk tekst gevonden wordt dat aan de regex voldoet, dan spreken we van een pattern match, een patroon-match.

In principe zijn reguliere expressies op twee manieren toe te passen. Je kunt programma's gebruiken die speciaal zijn geschreven om regexes op tekst los te laten, zoals grep, egrep en sed. De andere manier is door de regex-mogelijkheden van een programmeer- of scripttaal te gebruiken. Tegenwoordig bieden de meeste talen, bijvoorbeeld C, C++, Javascript, Python en PHP, functies en/of methoden om een regex op een stuk tekst toe te passen.

awk en in het bijzonder perl vallen er zo'n beetje tussen in. Als je perl eenmaal een beetje in de vingers hebt, zul je zien hoe stevig het concept van het toepassen van een regex op een stuk tekst in het gehele ontwerp van perl is geïntegreerd.
Pagina 3

Metakarakters

Om het over metakarakters te kunnen hebben, dienen we eerst vast te stellen wat "normale" karakters binnen een regex betekenen. De regex kat vindt inderdaad de "kat" in de tekst De kat van de buren piest op mijn gazon, maar ook de "kat" in de winterkatalogus. Dus, reguliere expressies werken puur op tekstueel niveau; ze kijken niet naar de semantiek. Het is belangrijk in te zien dat bovenstaande regex niks meer betekent voor de regex motor betekent dan een 'c', gevolgd door een 'a', gevolgd door een 't', waar deze reeks zich dan ook mag bevinden in de tekst waar de regex op is toegepast.

Om je op weg te helpen is hier een simpel voorbeeld. fruit.txt bevat een lijstje van soorten fruit, acht in totaal, één per regel. Als je het voorbeeld eenmaal gedownload en opgeslagen hebt, open dan een console (of DOS-venster of zo) en ga naar de directory waar je het bestand hebt opgeslagen. Als je daar bent, type dan het volgende:

$ egrep peer fruit.txt
peer

Het is niet de meest spetterende demonstratie van reguliere expressies in actie, maar als je dezelfde uitvoer krijgt, namelijk peer, dan betekent dat dat je met succes je eerste regex hebt toegepsst. Aangenomen dat dit je eerste keer is, natuurlijk.

Een ander voorbeeld is:

$ egrep pe fruit.txt
appel
sinaasappel
peer
perzik

Deze is al iets interessanter. De regex pe pakt elke regel die pe bevat, benadrukkend dat reguliere expressies totaal geen oog hebben voor semantiek. Nog een instructief voorbeeld is:

$ egrep an fruit.txt
banaan

Je vraagt je misschien af wat er zo bijzonder is aan dit voorbeeld. Als je je herinnerd dat egrep alleen die regels afdrukt die het patroon passen, vraag je je misschien af hoe egrep omgaat met het toepassen van an op banaan; misschien denk je dat het de regel twee keer pakt, wat meer is dan één, en dus wordt de regel afgedrukt. Het punt is dat egrep stopt met het toepassen van de regex op de regel zodra het een match vindt. Zodra het de eerste an vindt, houdt het op met zoeken, drukt de regel af en gaat door naar de volgende.

Dit specifieke voorbeeld illustreert dat egrep niet geïnteresseerd is in wat het patroon past, of hoe vaak, maar alleen of het past of niet. Later komen we nog voorbeelden tegen waar het wel uitmaakt wat en hoe vaak iets wordt gepast. Uiteraard maken deze voorbeelden geen gebruik van egrep.

Het laatste voorbeeld van deze sectie laat een feature van egrep zien:

$ egrep -v a fruit.txt
peer
perzik
druif
bosbes
pruim

De -v optie vertelt egrep om de zin van het passen te inverteren. Hierdoor worden alleen regels afgedrukt die het patroon niet passen. En inderdaad, geen van de afgedrukte regels bevat een 'a'.

3.1. Ankers
Met ^ en $ kun je een regex dwingen om alleen aan het begin of eind van een regel te passen, respectievelijk. Zo past ^kat alleen die regels die beginnen met kat, en kat$ alleen regels die eindigen met kat.

Een probeervoorbeeld dat dezelfde fruit.txt gebruikt als in de vorige sectie is de regex ^p:

$ egrep ^p fruit.txt
peer
perzik
pruim

Zoals je ziet slaagt deze regex er niet in om appel of sinaasappel te passen. Het feit dat ze op een andere plek wel een 'p' bevatten doet er niet toe. Vergelijkbaar pakt de regex l$ alleen appel en sinaasappel:

$ egrep 'l$' fruit.txt

appel
sinaasappel

Denk om de quootjes! In de meeste shells heeft het dollarteken een speciale betekenis. Door enkele quootjes (geen dubbele quootjes of backticks (`)) om de regex te zetten wordt de regex bij wijze van spreken beschermd tegen de shell. Het is in het algemeen wel een goed idee om enkele quootjes om je regex te zetten, dus dat zal ik vanaf hier ook in de voorbeelden doen.

De draad weer oppakkend, ^kat$ pakt regels die exact kat bevatten. Op dezelfde manier kun je lege regels vinden met ^$. Als je het wat lastig vindt om dat in te zien, pas dan gewoon de definities toe. De regex zegt in feite: "Pas een begin-van-de-regel, gevolgd door een einde-van-de-regel". Da's inderdaad wel zo'n beetje wat een lege regel inhoudt, niet?

Bedenk wel, een regex met alleen een begin-van-de-regel anker ^ past altijd, aangezien elke regel een begin heeft. Hetzelfde geldt natuurlijk voor een einde-van-de-regel anker. Als je me niet gelooft, probeer het dan maar uit op de fruitlijst:

$ egrep '^' fruit.txt
appel
sinaasappel
peer
perzik
druif
banaan
bosbes
pruim

Een boel regex implementaties bieden de mogelijkheid om woordankers te gebruiken. Zoals je kon zien vindt een regex als kat niet alleen het woord kat, maar ook alle gevallen waar kat verstopt zit in andere, langere woorden. In die gevallen kun je begin-van-woord en einde-van-woord ankers gebuiken, respectievelijk \< en \>. Deze metakarakters passen niet op karakters, maar ertussen.

Dus als je alleen op zoek bent naar gevallen van het woord kat, zou je de regex \<kat\> kunnen gebruiken.

Voor het volgende doe-voorbeeld heb je het katten.txt bestand nodig, met een aantal woorden waar kat in voorkomt. Probeer eerst het volgende:

$ egrep '\<kat' katten.txt
kat
kattevoer
katalogus
magere kat

Met dit voorbeeld wordt duidelijk dat start-van-woord grenzen niet alleen werken tussen woorden, maar ook aan het begin van de regel.

Deze woordgrensankers worden echter niet door alle regex-implementaties ondersteund. Een aantal implementaties (waaronder die van perl) biedt in plaats daarvan is-woord-grens en geen-woord-grens ankers, in welk geval de regex \<kat\> vervangen moet worden door \bkat\b.

In deze context dient het begrip "woord" licht opgevat te worden; elke combinatie van letters (boven- en onderkast), de underscore ( _ ) en cijfers telt als een woord wanneer je met woordgrensankers bezig bent.
Pagina 4

Karakterklassen

Middels de […] constructie kun je aangeven dat op een bepaalde positie binnen het patroon een van meerdere karakters mag voorkomen. Neem bijvoorbeeld eens aan dat je op zoek bent naar zowel bink als bonk. In dat geval zou je de b[io]nk regex kunnen gebruiken.

Een ander voorbeeld, het herkennen van hexadecimale cijfers, is [0123456789abcdefABCDEF]. Dit wordt echter al snel onpraktisch. Gelukkig kun je een minteken gebruiken om een bereik (of interval) aan te geven: [0-9] is effectief gelijk aan [0123456789]. Meerdere bereiken in een karakterklasse mag ook: [0-9a-fA-F].

Denk er alleen wel aan om niet [A-z] te gebruiken wanneer je [A-Za-z] bedoelt. Hoewel het er handig uitziet, pakt de eerste regex ook de zes karakters tussen de 'Z' en 'a' (als je tenminste de ASCII karakterset gebruikt).

Je kunt ook een genegeerde karakterklasse (genegeerd als in negatie) aangeven door een dakje (^) direct achter het openingshaakje te zetten: [^…]. Dit negeert de zin van de karakterklasse: [^0-9] past alle karakters behalve cijfers.

Alles goed en wel, maar wat nou als je die haakjes, minteken en dakje binnen je karakterklasse wil gebruiken? Een manier is om ze te escapen met een backslash: [\^\]]. Een andere is om ze op plaatsen te zetten waar ze niet geldig zijn; de regex motor zal ze dan letterlijk interpreteren. Dus, plaats het minteken als eerste of laatste in de karakterklasse, het dakje op elke behalve de eerste plaats, en het sluitingshaakje direct achter het openingshaakje: []^[-] is een geldige karakterklasse van vier karakters.
Pagina 5

De Punt

De punt, ., kun je beschouwen als een speciale karakterklasse, in dezen dat het elke willekeurige karakter past. d.t bijvoorbeeld, past zowel dit als dat, maar ook dqt, d#t, etc.

Dit betekent dat een regex om een IP-adres te vinden, bijvoorbeeld 209.204.146.22, niet werkt. Alledrie de punten moeten worden ge-escaped: 209\.204\.146\.22 werkt wel zoals gewenst. Nou ja, er zouden nog cijfers voor of achter het IP-adres kunnen staan. Dat kun je oplossen door gebruik te maken van woordankers: \<209\.204\.146\.22\>.

Binnen een karakterklasse verliest de punt echter zijn betekenis. Een karakterklasse om naar interpunctie te zoeken zou er bijvoorbeeld zo uit kunnen zien: [.,:;].
Pagina 6

Kwantificeerders

Met kwantificeerders (quantifiers) kun je aangeven hoe vaak een karakter, karakterklasse of groep opeenvolgend mag of moet voorkomen. De algemene vorm is {min,max}.

Een voorbeeld is de regex bo{1,2}t, welke zowel bot als boot past. En om elke opeenvolging van drie tot en met vijf klinkers te passen, kun je [aeiou]{3,5} gebruiken. Ook kun je een kwantificeerder gebruiken om iets optioneel te maken: vindt{0,1} past zowel vind als vindt. Deze constructie komt vaak genoeg voor om een afkorting te verantwoorden: de regex vindt? is effectief identiek met de voorgaande.

Belangrijk om op dit punt op te merken is dat een kwantificeerder alleen van toepassing is op het direct voorgaande element. Het vraagteken in bovenstaande regex slaat alleen op t, en niet het hele vindt.

Als je iets een bepaald aantal keren wil passen, kun je het minimum gelijkstellen aan het maximum: ^-{80,80}$ past regels die uitsluitend bestaan uit tachtig streepjes. Sommige regex-implementaties staan toe dat deze vorm kan worden afgekort tot {num}. Hiermee kan de vorige regex worden ingekort tot ^-{80}$.

Het is ook toegestaan om de bovengrens weg te laten: a{5,} past elke opeenvolging van tenminste vijf letters 'a'. Het geval van "een of meer" (bijv. a{1,} komt echter veel vaker voor. Daarom is er voor deze vorm een afkorting, de +: a+ en a{1,} zijn effectief gelijk.

Het geval "nul of meer" heeft ook een verkorte vorm: *. Bijvoorbeeld, e* past elk opeenvolgend aantal letters 'e', inclusief nul. Maar pas op: een regex zal altijd proberen om zo "vroeg" (links) mogelijk te passen. Dus als je verwacht dat deze regex, toegepast op beer, de vetgedrukte tekst past, heb je het mis! Dat komt omdat er een opeenvolging van e's aan het begin van de tekst staat, nog voor de b. Het feit dat de opeenvolging nul karakters lang is maakt voor de regex geen verschil. In zo'n geval is de regex e+ dus veel toepasselijker.

Belangrijk om te weten is dat kwantificeerders gulzig (greedy) zijn. Dat betekent dat wanneer je de regex 1* toepast op 11111, het alle 1'en consumeert. Pas wanneer de gulzigheid van een kwantificeerder de oorzaak van een patroon mis-match dreigt te worden zal de kwantificeerder een deel van de tekst die het heeft geconsumeert karaktergewijs teruggeven.

Neem bijvoorbeeld de regex [0-9]*25 bijvoorbeeld, welke getallen past die op 25 eindigen. Als je dit op de tekst 3425 toepast, zal de kwantificeerder eerst de hele tekst consumeren, omdat alle karakters de karakterklasse [0-9] passen. Maar dat voorkomt dat 25 kan passen, waardoor de regex in zijn geheel faalt.

In zulke gevallen zal de kwantificeerder één karakter per keer vrijgeven. Eerst wordt de 5 vrijgegeven, waardoor de kwantificeerder slechts nog 342 past. Wanneer blijkt dat dat nog niet genoeg is, wordt ook de 2 vrijgegeven, waardoor de rest van de regex, 25, ook past.

Dit betekent dat een regex die veel kwantificeerders bevat, een heleboel combinaties moet proberen voor deze faalt. Dus als de tekst waarop de regex wordt toegepast veel bijna-matches veroorzaakt, kan het opeens heel lang duren om de data te verwerken.
Pagina 7

Alternatie

Met het | metakarakter, de of (or), kun je meerdere regexes samenvoegen tot één regex. Hiermee voorzie je de regex motor van alternatieven. Jut en Jul zijn twee verschillende regexes, waar Jut|Jul er één is die zowel Jut als Jul past.

Verder terug had ik het over de regex b[io]nk. Met alternatie zou je dit (op een ineffeciëntere manier) kunnen schrijven als b(i|o)nk, waar de haakjes (welke dus ook metakarakters zijn, straks meer hierover) gebruikt worden om het bereik van de alternatie te beperken.

Nog een, bijna klassiek, voorbeeld is de regex ^(From|Subject|Date):• waarmee je de headers uit een e-mail bericht kunt filteren. In dit voorbeeld zijn de haakjes geenszins optioneel; de regex ^From|Subject|Date:• past iets heel anders. Door de regex uit elkaar te trekken krijg je drie aparte regexes, ^From, Subject en Date:•, wat (hoop ik) duidelijk maakt waarom de regex verkeerd is (als in, niet geschikt voor het filteren van e-mail headers).
Pagina 8

Groeperen

Naast het beperken van het effect van alternatie hebben haakjes (…) nog een functie, namelijk het groeperen (grouping) voor kwantificeerders. Alles over kwantificeerders dat op karakters en karakterklassen van toepassing is, geldt ook voor groepen.

Een voorbeeld is (hoera•){2,3}, welke zowel hoera hoera alsook hoera hoera hoera past.

Een complexer voorbeeld combineert alternatie en groepering met een kwantificeerder: (hoera |hoezee ){2,3}. Dat levert twaalf mogelijke combinaties op, waaronder bijvoorbeeld hoera hoezee en hoezee hoera hoezee.
Pagina 9

Terugverwijzingen

Bij gebrek aan een betere term heb ik "backreferences" vertaald als "terugverwijzingen". Als iemand een term heeft die beter bekt, dan hoor ik dat graag.

Het groeperen heeft een uiterst nuttig neveneffect. Dat komt omdat bepaalde regex-implementaties de in een groep gepaste tekst "onthouden", en deze beschikbaar stellen, tijdens en soms zelfs na het toepassen van de regex.

Neem eens aan dat je in een stuk tekst op zoek bent naar dubbele woorden, zoals …dus•dus…. Nou zou je kunnen proberen om een aparte regex te schrijven voor elk woord dat je maar kan bedenken, maar zou het niet makkelijk zijn als je zoiets kon zeggen als, "zoek iets wat dit patroon past, en pas het dan nog eens"?

Dat kan. Vooropgesteld dat de regex implementatie het ondersteunt, "onthouden" haakjes ((…)) wat ze passen. In dat geval zou je op dubbele woorden kunnen zoeken met de regex ([a-zA-Z]+)\1. Het metakarakter \1 wordt een terugverwijzing (backreference) genoemd.

Deze regex past echter ook gevallen als dus dusdanig, daarom is in dit geval ([a-zA-Z]+)•\1\> een betere regex.

Om te bepalen welke terugverwijzing bij welke groep hoort, dien je het aantal openingshaakjes te tellen vanaf links. In bovenstaand voorbeeld was maar één groep in het spel, dus dat is makkelijk. Bij het volgende voorbeeld ligt het wat ingewikkelder. ((de|een) (grote( rode)?|kleine( gele)?) (auto|fiets)) bevat zes groepen. Het voorbeeldbestand (auto.txt) bestaat uit vijf regels, waarvan er vier door de regex gepast kunnen worden:

$ egrep '((de|een) (grote( rode)?|kleine( gele)?) (auto|fiets))' auto.txt
de grote rode auto
een kleine fiets
de kleine gele auto
een grote rode fiets

Om het wat duidelijker te maken welke terugverwijzing bij welke groep hoort, heb ik een perl-scriptje geschreven. Dit geeft de volgende uitvoer:

$ perl -n refs.pl auto.txt
"de grote rode auto"
\1 => de grote rode auto
\2 => de
\3 => grote rode
\4 => rode
\5 => (null)
\6 => auto

"een kleine fiets"
\1 => een kleine fiets
\2 => een
\3 => kleine
\4 => (null)
\5 => (null)
\6 => fiets

"de kleine gele auto"
\1 => de kleine gele auto
\2 => de
\3 => kleine gele
\4 => (null)
\5 => gele
\6 => auto

"een grote rode fiets"
\1 => een grote rode fiets
\2 => een
\3 => grote rode
\4 => rode
\5 => (null)
\6 => fiets

Het scriptje past de regex op elke regel van het voorbeeldbestand toe, en drukt de terugverwijzingen af als de regex de regel past. Hierbij geeft (null) aan dat de groep waar de terugverwijzing op terugslaat geen deel uitmaakt van de match.

Je kan dus meerdere groepen in een regex gebruiken, maar het maximum aantal terugverwijzingen is in de meeste regex-implementaties beperkt tot negen (\1 ... \9).

Een wat groter voorbeeld is het ontrafelen van de query string in een URL, zoals bijvoorbeeld http://www.foobar.com/search?query=regex&view=detailed.

Neem nou eens aan dat we de naam en waarde van de query variabele uit deze URL willen hebben. Dit kan gedaan worden met de regex \?([a-zA-Z]+)=(^&]+). In deze regex gebruiken we \? om de regex uit te lijnen op de query gedeelte, welke direct na het vraagteken volgt. Vervolgens passen we de naam van een variabele met [a-zA-Z]+, en zetten het tussen haakjes om het voor later gebruik op te slaan, ([a-zA-Z]+). Dit wordt gevolgd door een is-gelijk teken, dus voegen we = toe aan de regex. Tenslotte moeten we de waarde van de variabele "vangen". Dit kan met [^&]+, aangezien de string waaruit de waarde bestaat doorloopt tot de volgende &, welke dienst doet als scheidingsteken in de naam=waarde reeks. Dit werkt ook als de waarde niet gevolgd wordt door een ampersand, want in dat geval is de rest van de waarde van de variabele gewoon de rest van de URL. De waarde-regex moet tussen haakjes worden gezet aangezien we de waarde willen opslaan voor later, dus krijgen we ([^&]+).

Hoewel er twee paar haakjes in de regex staan, wordt geen van beide in de regex als terugverwijzing gebruikt. Hoe komen we dan bij de data? Nou, dat hangt sterk af van de tool waarin de regex wordt gebruikt. Hier volgen wat voorbeelden.

Met perl is de inhoud van beide terugverwijzingen na het passen beschikbaar in de variabelen $1 en $2. Het volgende stukje code laat zien hoe je dat kunt gebruiken.

$url = 'http://www.foobar.com/search?query=regex&view=detailed';;
$url =~ /\?([a-zA-Z]+)=([^&]+)/;
print "$1 = $2\n";

In PHP dien je de verzameling van ereg()-functies te gebruiken (zie de handleiding), zoals bijvoorbeeld:

$url = 'http://www.foobar.com/search?query=regex&view=detailed';;
ereg('\?([a-zA-Z]+)=([^&]+)', $url, $refs);
echo "$refs[1] = $refs[2]\n";
Pagina 10

Ten slotte

Het meeste van wat ik van reguliere expressies weet heb ik uit het boek Mastering Regular Expressions, geschreven door Jeffrey Friedl en uitgegeven door O'Reilly. Voor meer applicatie-gerichte informatie over reguliere expressies zou je O'Reilly's boeken over sed & awk of perl kunnen proberen.

Als je een PHP programmeur bent, lees dan vooral de onderdelen in de handleiding die over de ereg (POSIX) en preg (Perl-compatible) verzamelingen regex-functies gaan.

Perl programmeurs kunnen ofwel het onderdeel over reguliere expressies in de handleiding op Perldoc.com lezen, of je kunt proberen man perlre achter een shell prompt in te typen (als je tenminste een UN*X-achtig OS draait).


Comment Wout:
Ik vond deze tutorial erg nuttig voor het inzicht in reguliere expressies, er is immers (te) weinig over te vinden op het i-net..
De bron van deze tutorial is te vinden op:
http://www.phpgg.nl/node/406

Reacties

0
Nog geen reacties.