Reguljära uttryck är en sekvens med tecken som bildar ett sökmönster. Något som liknar reguljära uttryck är när vi letar efter filer som slutar med exempelvis .txt med kommandot ls *.txt i Linux. Detta är dock inte ett reguljärt uttryck, utan något som kallas för wildcard (på svenska ofta översatt till jokertecken). Ett annat namn är shell filename globbing (bra svensk översättning saknas). Men det liknar åtminstone ett reguljärt uttryck.

Medan wildcards och filename globbing endast är enstaka tecken, är reguljära uttryck ett helt språk. Reguljära uttryck är också en del av datavetenskapen.

Ett exempel på ett reguljärt uttryck är a..a som matchar alla ord som slutar och börjar på bokstaven a, och har två valfria tecken i mitten. Detta matchar till exempel anna, alla, aina och så vidare.

Dessvärre finns det några olika dialekter av reguljära uttryck. Det är främst tre olika varianter som vi kommer i kontakt med i Linuxsystem. Dessa är:

  • POSIX BRE (Basic Regular Expressions). Detta är vad som vanliga grep använder i GNU/Linux. Det fungerar bra för enklare saker, men saknar en del funktionlitet. Dessutom har BRE lite märklig syntax när man ska använda {} för upprepningar, och () för grupperingar. Dessa måste då escapas med \.

  • POSIX ERE (Extended Regular Expressions). Detta är den typ som vi kommer att fokusera på i den här delen av artikelserien. ERE används av egrep, som står för just extended grep. Samma funktionalitet fås med grep -E. ERE är en utökning av just grep. ERE har också en förenklad syntax när det gäller exempelvis upprepningar med {}, och påminner dessutom en del om PCRE.

  • PCRE (Perl Compatible Regular Expressions). Detta är den mest använda typen av reguljära uttryck i programmeringsspråk. Det används bland annat i språk som Perl, PHP, Python med flera. Även grep har experimentellt stöd för PCRE. Notera dock att stödet i grep är just experimentellt, och en del funktioner saknas.

I denna del av artikelserien kommer vi att fokusera på kommandot egrep i Linux, och därmed POSIX ERE.

Några exempel på egrep kan vara på sin plats. Lås oss nu lista alla användare i ett Linuxsystem som har ett UID mellan 1000 och 1009.

$> egrep "100[0-9]" /etc/passwd
jackbenny:x:1000:1000:Jack-Benny:/home/jake:/bin/bash
bob:x:1002:1002::/home/bob:/bin/bash

"100[0-9]" betyder alltså 1000, 1001, 1002, 1003 och så vidare upp till 1009. [0-9] är en så kallad teckenklass. Här får det förekomma tecknen 0-9. De får dessutom bara förekomma en enda gång. Vill vi försäkra oss om att inga andra tecken följer 0-9 kan vi sätta ett kolon efter. Kolont matchar då fältseparatorn i filen. Efter fältet tar slut vid fältseparatorn är vi säkra på att inga andra tecken kan följa. Sökmönstret blir då istället "100[0-9]:".

Ett litet mer intressant exempel kan vara att hitta alla rader i Alices adventures in Wonderland där någon springer. Texten hämtas här från min personliga webbsida med curl. Texten omdirigeras sedan till egrep med en rörledning (engelska pipe).

Har du inte curl installerat, så installerar du det enklast med din pakethanterare. -s till curl betyder att curl ska vara tyst (silence), och inte visa nedladdningsinformation eller mätare - bara texten.

Hela kommandot för att hämta texten och omdirigera datan till egrep blir:

$> curl jackbenny.se/docs/alice.txt -s | egrep "\b[Rr](u|a)n\b"
Rabbit with pink eyes ran close by her.
take out of it, and burning with curiosity, she ran across the
existence; `and now for the garden!' and she ran with all speed
you doing out here?  Run home this moment, and fetch me a pair of
that she ran off at once in the direction it pointed to, without
  `He took me for his housemaid,' she said to herself as she ran.
enough to get through the door, she ran out of the house, and
ran off as hard as she could, and soon found herself safe in a
dodged behind a great thistle, to keep herself from being run
moment to be trampled under its feet, ran round the thistle
so she set off at once, and ran till she was quite tired and out
  Alice laughed so much at this, that she had to run back into
gardeners, who ran to Alice for protection.
croqueted the Queen's hedgehog just now, only it ran away when it
disappeared; so the King and the executioner ran wildly up and do
  `What trial is it?' Alice panted as she ran; but the Gryphon
only answered `Come on!' and ran the faster, while more and more
curious dream, dear, certainly:  but now run in to your tea; it's
getting late.'  So Alice got up and ran off, thinking while she
ran, as well she might, what a wonderful dream it had been.

Varje rad i texten här innehåller alltså något av orden Run, Ran, run, ran.

\b i uttrycket betyder word boundary, alltså att vill vi avgränsa sökningen så att resten av vårt uttryck bara ska tolkas som ett helt ord. Det får alltså inte var en del av ett annat ord.

[Rr] betyder att ordet kan börja med både “R” och “r”.

(u|a) betyder att nästa bokstav kan vara antingen “u” eller “a”.

n är just vad det är, ett ensam “n”.

\b markerar slutet på ordet, alltså ytterligare en word boundary. Vi har alltså en word boundary framför ordet och en efter ordet.

Om vi vill begränsa sökresultatet ytterligare kan vi säga att vi enbart är intresserade av rader som börjar med något av orden Run, Ran, run eller ran. Detta gör med specialtecknet ^.

$> curl jackbenny.se/docs/alice.txt -s | egrep "\b^[Rr](u|a)n\b"
ran off as hard as she could, and soon found herself safe in a
ran, as well she might, what a wonderful dream it had been.

Hade vi istället varit intresserade av rader som slutar med vårt sökord hade vi istället kunnat lägga till $ i slutet av det reguljära uttrycket.

Skulle vi vilja hitta alla rader som slutar på off eller of kan vi använda {} för att specificera att f får lov att förekomma en till två gånger.

$> curl jackbenny.se/docs/alice.txt -s | egrep "\bof{1,2}\b$"
...
King, the Queen, and Alice, were in custody and under sentence of
Bill, the Lizard) could not make out at all what had become of
  As soon as the jury had a little recovered from the shock of
 `Are they in the prisoner's handwriting?' asked another of
Lizard as she spoke.  (The unfortunate little Bill had left off
head on her hand, watching the setting sun, and thinking of
  Lastly, she pictured to herself how this same little sister of
with many a strange tale, perhaps even with the dream of

Det finns en hel uppsättning specialtecken och andra tecken - som ofta kallas metatecken - som vi kan använda i reguljära uttryck. I nedanstående tabell listas dessa metatecken tillsammans med några exempel.

Metatecken Matchar
. Matcha ett valfritt tecken. Exempelvis a. matchar aa, ab, ac, a!, a? och så vidare.
[ ] Anger en teckenklass. Exempelvis 20[2-8] matchar 202, 203, 204 upp till 208. [ij]p matchar ip och jp.
[^ ] Anger en teckenklass som inte får förekomma. Exempelvis [^Rr]un matchar sun, pun, can, an etc.
? Tecknet eller klassen vid ? får förekomma endast en gång men måste inte finnas. Exempelvis jag? matchar både ja och jag.
* Tecknet eller klassen vid * får lov att förekomma hur många gånger som helst, även noll. Exempelvis ab*a matchar aa, aba, abba, abbba, abbbba och så vidare.
+ Tecknet eller klassen vid + måste förekomma en gång, men flera är tillåtna. Exempelvis ab+a matchar aba, abba, abbba och så vidare.
{min,max} Tecknet eller klassen vid {} måste förekomma min antal gånger, men max antal gånger. Exempelvis a[bc]{1,3}a matchar aba, aca, abca, abbca och så vidare. Men abbcca matchar inte, då detta går över max.
^ Matchar början på en rad. Exempelvis ^sol matchar sol, men endast om det står första tecknen på rad.
$ Matchar slutet på en rad. Exempelvis sol$ matchar sol, men endast på det står som sista tecknen på en rad.
\b Word boundaries. Används för att avgränsa ord. Exempelvis \bDator\b matchar ordet dator, om det står som ett ensamt ord. Datorskärm matchar exempelvis inte.
( ) Används för att gruppera uttryck, tecken eller alternation (se nedan).
| Alternativ. Matchar antingen tecknen till höger eller vänster om |. Exempelvis a(p|(bb))a matchar både apa och abba.
\ Escape. Används för att ta bort den speciella betydelsen av ett metatecken, så att tecknet istället blir sökbart. Exempelvis \. söker efter en punkt, inte ett valfritt tecken.