Valid HTML 4.01! Valid CSS
Anybrowser

Navigatie:


Home - Linux beginners - Reguliere expressies

logo

.



Home
Printbaar

Nieuws

Nieuwe distributie
Onlangs zijn we overgestapt op een nieuwe Linux-distributie, nl. Pardus Linux

Dit lijkt ons een prima distributie, zowel voor beginners als experts.



16. Reguliere Expressies

Een reguliere expressie is een soort formule om een bepaalde reeks tekens in een tekst te vinden. Net zoals jokertekens, maar dan met veel meer mogelijkheden. Veel (Linux-) programma's kunnen werken met reguliere expressies, bv. vi, grep, sed, perl, enz.

Veel mensen komen er niet toe om ze te gebruiken, omdat ze ingewikkeld lijken. Maar met wat oefening kunnen ze het leven van een computer-gebruiker heel wat aangenamer maken, omdat ze je heel wat routinewerk uit handen kunnen nemen.

Reguliere expressies zijn (meestal) samengesteld uit "gewone" tekens en zgn. metacharacters. Gewone tekens bevatten (hoofd- en kleine-) letters en/of cijfers. Metacharacters hebben een speciale betekenis, die we straks zullen beschrijven.

De eenvoudigste toepassing van een reguliere expressie ziet eruit als een normale string (een string is een rijtje, of slechts één, "gewone" tekens). Zo bevat de reguliere expressie boos geen metacharacters. Deze expressie zal op de woorden boos en boosaardig passen, maar niet op bv. Boos (vanwege de hoofdletter...).

Maar om echt gebruik te kunnen maken van reguliere expressies, is het nodig om een goed begrip te hebben van metacharacters. Hieronder staan ze op een rijtje:

MetacharacterBeschrijving
. Een enkel "gewoon" teken. De reguliere expressie r.t zal passen op bv. rat, r t, rot en rit, maar niet op roet.
$ Betekent: het eind van een regel. De reguliere expressie haar$ zal passen op de string Hij heeft weinig haar, maar niet op De kat verhaart.
^ Betekent: het begin van een regel. Zo slaat de reguliere expressie ^hoe wel op hoe en waarom, maar niet op waarom en hoe
* Zoekt naar het voorkomen van nul of meer keer het er direct aan voorafgaande teken. Bv. betekent .* elke willekeurig aantal (dus ook nul) tekens.
\ Is een zgn. escape-character, bedoeld om van een metacharacter een gewoon teken te maken. Stel, dat je in een tekst naar het dollar-teken zoekt, dan kun je niet de reguliere expressie $ gebruiken, omdat dit een meta-character is, dus gebruik je \$, om aan te geven, dat het je om het letterlijke $-teken gaat.
[ ] Past op elk teken, dat tussen de haken staat. De reguliere expressie r[aiu]t zal passen op rat, rit en rut, maar niet op rot. Je kunt ook een tekenreeks opgeven. Met [0-9] wordt bv. elk willekeurig cijfer bedoeld. Ook meerdere reeksen zijn mogelijk: [A-Za-z] betekent: elke hoofd- of kleine letter. Om aan te geven, dat de tussen de haken staande tekens juist niet gevonden moeten worden, gebruik je als eerste teken na de openingshaak een ^. Bv.: [^029] zal passen bij elk teken, behalve bij de 0, de 2 en de 9.
\< \> Betekent: het begin (\<) of het eind (\>) van een woord. Bv. \<def past bij definitief, maar niet bij gedefinieerd.
Let op: dit meta-character wordt niet door elke toepassing ondersteund.
\( \) Behandelt de expressie tussen \( en \) als een groep en bewaart de resultaten, die bij deze expressie passen in tijdelijke "buffers". Tot maximaal 9 bij de expressie passende resultaten kunnen opgeslagen worden in die buffers. De buffers zijn op te roepen als \1 t/m \9. Lijkt ingewikkeld, maar met de later volgende voorbeelden, wordt het wel duidelijk.
| Betekent en/of. Bijvoorbeeld: (hem|haar) past bij de regels Het is van hem en Het is van haar, maar niet bij Het is van hen.
Ook dit meta-character wordt niet door elke toepassing ondersteund.
+ Zoekt naar het één of meer keer voorkomen van de direct aan het +-teken voorafgaande teken of expressie. Bv.: de reguliere expressie 9+ past bij 9, 99 en bij 99999.
Ook dit meta-character wordt niet door elke toepassing ondersteund.
? Past bij het 0 of 1 keer voorkomen van het teken of de expressie die direct aan het ?-teken vooraf gaat.
Ook dit meta-character wordt niet door elke toepassing ondersteund.
\{i\}
\{i,j\}
De betekenis hiervan is het best duidelijk te maken met een voorbeeld:
A[0-9]\{3\} zal passen bij A gevolgd door precies 3 cijfers, bv. A572, dus niet bij A9836, want hier staan 4 cijfers achter de A.
De expressie [0-9]\{4,6\} bekent het voorkomen van precies 4, 5 of 6 cijfers.
De expressie [0-9]\{3,\} betekent het voorkomen van 3 of meer cijfers.
Ook dit meta-character wordt niet door elke toepassing ondersteund.

Zoals bij een aantal meta-characters al wordt aangegeven, werken ze niet allemaal bij elke toepassing. Dat komt omdat er meerdere "dialecten" van reguliere expressies bestaan. Zo zal het laatste in bovenstaande tabel genoemde meta-character (\{i\} prima werken bij grep, maar het meta-character + doet het daar niet, maar wel weer bij vi.
In de man-pages van de diverse toepassingen is vaak terug te vinden, welk dialect de betreffende toepassing "spreekt".
Toch hieronder nog even een tabel met een overzicht van welke meta-characters door welke toepassingen ondersteund worden (aangegeven met een "X"). De hier niet genoemde meta-characters doen het in alle genoemde toepassingen.

Toepassing\( \)\{ \}? +|( )
vi, fgrepX-----
awk--XXXX
sed, ex, grepXX----
Tcl, egrep, perlX-X XXX

Voorbeelden

We kunnen de werking van reguliere expressies het best verduidelijken met voorbeelden, waarbij dan ook nog het e.e.a. verteld kan worden over de toepassing, die we erbij gebruiken. Laten we beginnen met vi:

vi

Een mogelijkheid van vi, die we niet in het artikel over vi besproken hebben, is het vervangen van tekst. Dit wordt gedaan vanuit de "dubbele punt-mode" (geef een escape om in de opdracht-mode te komen en type daar een dubbele punt (:)).
De vervangingsopdracht ziet er (vauit de opdracht-mode) als volgt uit:

   :bereiks/patroon1/patroon2/g

De dubbele punt brengt je in de zgn.ex-mode. De hierna gegeven opdrachten hebben betrekking op het bestand, dat op dat moment bewerkt wordt.

bereik specificeert voor welke regels de opdracht geldt. Het procent-teken (%) geeft aan, dat het om alle regels gaat. Het dollar-teken ($) betekent: alleen de laatste regel.Je kunt ook zelf de regels specificeren, bv. 10, 20 betekent: regels 10-20; .,$ betekent: van de huidige regel tot de laatste; .+2, $-5 betekent: vanaf 2 regels na de huidige tot de vijfde regel boven de laatste.

s is de vervangings-opdracht.

patroon1 is de reguliere expressie, waarnaar gezocht wordt.

patroon2 is de "tekst", die als vervanging dient.

g is optioneel. Als je hem vermeldt, zal de vervanging gebeuren in alle aangegeven regels. Als je hem niet vermeldt, zal de vervanging alleen gebeuren bij de eerste keer, dat patroon1 gevonden wordt.

Voorbeelden:
Probeer ze met de hiervoor gegeven informatie voor jezelf uit te leggen!

:%s/ */ /gVervangt 1 of meer spaties achter elkaar door een enkele spatie.
:%s/ *$//Verwijdert alle spaties aan het eind van de regel.
:%s/^/ /gVoegt een spatie in aan het begin van iedere regel.
:%s/^[0-9][0-9]* //Verwijdert alle nummers van het begin van de regel.
:%s/p[aeio]t/put/gVervangt overal waar pat, pet, pit of pot voorkomt, deze in put
:%s/t\([aou]\)g/h1t/gVervangt elke tag, tog en tug door resp. hat, hot en hut

Het laatste voorbeeld hierboven is het lastigst: het maakt gebruik van \( \) en de buffer (\1).

sed

Ook hiervoor enkele voorbeelden:

sed 's/^$/d' tekst.txtVerwijdert alle lege regels.
sed 's/^[ \t]*$/d' tekst.txtVerwijdert alle regels, die alleen witruimte (spaties en tabs) bevatten.
sed 's/"//g' tekst.txtVerwijdert alle (dubbele) aanhalingstekens (")

Lees eventueel de man-pages van sed nog eens door of kijk nog eens naar het artikel over tekstgereedschappen om te begrijpen wat er in deze voorbeelden gebeurt.

grep

Dit is een opdracht, die eigenlijk gemaakt is om te werken met reguliere expressies. De afkorting grep betekent Global Regular Expression Print. Lees, om de voorbeelden te kunnen begrijpen eventueel de man-pages en/of het artikel over tekstgereedschappen nog eens door.

We gaan bij de hieronder genoemde voorbeelden uit van een bestand, genaamd tel.txt, dat een lijst bevat, met op elke regel een naam, gevolgd door een komma, dan de voornaam, gevolgd door een tab met daarna een (huis-)telefoonnummer:

   Francis, John	5-3871
   Wong, Fred		4-4123
   Jones, Thomas	1-4122
   Salazar, Richard	5-2522
grep '\t5-...1' tel.txtGeeft alle telefoonnummers uit tel.txt weer, die beginnen met een 5 en eindigen met een 1. De tab wordt aangegeven met \t.
grep '^s[^ ]* R' tel.txtGeeft alle regels weer, waarvan de achternaam begint met een S en de voornaam met een R.
grep '^[JW]' tel.txtGeeft alle regels weer, waarvan de achternaam begint met een J of een W.
grep '^[M-Z].*[12]' tel.txtGeeft alle regels weer, waarvan de achternaam begint met een letter uit de rij M t/m Z en waarvan het telefoonnummer eindigt op een 1 of een 2.

Slot

En hiermee eindigt het artikel over reguliere expressies. Het omgaan met deze materie is vooral een kwestie van veel oefenen. Misschien kun je er een sport van maken om allerlei problemen op te zoeken, die wellicht zijn op te lossen met reguliere expressies, zoals bijvoorbeeld:

  • Het controleren van een email-adres.
  • Het verwijderen van HTML-tags uit een tekst.
  • Het omwisselen van 2 kolommen in een tabel.
  • Enz., enz.

Want, zoals bij zoveel zaken: oefening baart kunst!.

Laatst herzien op 18-12-2006