Reguljära uttryck
I detta steg fortsätter vi att gå igenom olika sätt att arbeta med textfiler genom att introducera sökning med hjälp av reguljära uttryck.
- Filtrering
- Introduktion till reguljära uttryck
- Konstruktion av reguljära uttryck
- Sammanfattning och diagnos
Filtrering
I detta avsnitt kommer vi att använda filerna resultat1.txt och resultat2.txt som innehåller några godtyckliga resultat för några påhittade personer. Spara dessa filer och använd dem till övningarna längre ner.
Kommandot
grep
används för att visa alla rader i en fil som innehåller ett viss ord eller en sekvens av tecken i allmänhet. Vi kan söka efter texten
Johan
i den första resultatfilen med följande kommando:
turte123@li10-3:-$ grep Johan resultat1.txt
Johanna Rönnberg 9 15 13
Göran Johansson 16 19 15
Yngve Johanson 10 11 8
Alla rader som innehåller texten
Johan
visas på skärmen, men svaret kanske inte blev vad vi förväntade oss. Kommandot
grep
hittar alla förekomster av
Johan,
även när det ingår som en del i andra namn. Om vi vill söka efter namnet Johan kan vi t.ex. söka efter "Johan " med ett mellanslag efter sista bokstaven. Då måste vi också omge argumentet till
grep
med citattecken.
Ett annat sätt att bara hitta namnet Johan är att använda flaggan
-w
.
Det finns många olika flaggor som man kan använda för att modifiera det sätt som
grep
söker. Nedanstående tabell visar några av de mer användbara:
Flagga | Betydelse |
---|---|
-i |
Gör ingen skillnad på små och stora bokstäver |
-v |
Sök efter rader som inte matchar det givna ordet |
-w |
Sök efter den angivna texten som ett ord, dvs det måste finnas avgränsning runt ordet |
-n |
Skriv ut radnummer för alla rader som hittas |
-c |
Skriv enbart ut antalet hittade rader, inte raderna i sig |
Med hjälp av
grep
och dessa flaggor kan vi besvara olika frågor kring våra resultatfiler. Vilka personer har ett namn där texten "lind" ingår och på vilka rader i filen finns de?
turte123@li10-3:-$ grep -i -n lind resultat1.txt
18:Ingrid Lindgren 8 13 13
21:Elisabeth Björklind 15 12 10
Vi kan söka i flera filer genom att ange dessa efter varandra som argument till
grep
.
Vilka personer, i båda filerna, har resultat 17 i någon av tabellerna?
turte123@li10-3:-$ grep 17 resultat1.txt resultat2.txt
resultat1.txt:Mikaela Andersson 14 - 17
resultat1.txt:Annica Rundgren 17 10 15
resultat1.txt:Mats Karlzon 15 17 10
resultat2.txt:Lina Larsson 13 17 7
resultat2.txt:Ann Nordenberg 17 14 14
Hur många personer i den andra filen har resultat i samtliga tre tabeller, dvs texten " -" finns inte någonstans på raden?
turte123@li10-3:-$ grep -c -v " -" resultat2.txt
19
Observera att vi här angivit ett mellanslag innan bindestrecket för att vi inte ska matcha dubbelnamn, t.ex. Jan-Erik.
Övning
Hur många personer i den första filen har ett namn som slutar på son?
Lösningsförslag
Introduktion till reguljära uttryck
Med hjälp av
reguljära uttryck
(eng. regular expressions)
kan vi söka efter mer komplicerade mönster med
grep
.
Hur söker man t.ex. efter alla stavningar av namnet Karlsson? Det kan stavas med C eller K, med ett eller två s, eller till och med med z. Genom att formulera ett reguljärt uttryck kan vi med en enda sökning hitta alla förekomster av dessa stavningar. Detta ska vi se längre ner i detta avsnitt.
Reguljära uttryck har stora likheter med jokertecken som vi använder i skalet för ange flera filer samtidigt, men de är mer kraftfulla. Reguljära uttryck förekommer inte bara som sökmönster till
grep
utan dyker upp på flera andra ställen i UNIX. Det är också en av utgångspunkterna när det gäller studier av formella språk. Därför är det nyttigt för nästan alla som kommer i kontakt med datorer att åtminstone känna till begreppet.
När vi använder reguljära uttryck för att söka med
grep
är grundtanken är att man med hjälp av vissa specialtecken formulerar ett mönster som kan matcha flera olika ord eller teckensekvenser. De enklaste reguljära uttrycken består enbart av bokstäver och dessa såg vi exempel på i förra avsnittet. Om man söker efter
abc
så hittar
grep
enbart de rader som innehåller teckensekvensen
abc.
Enstaka tecken
För att söka efter mönster som innehåller godtyckliga tecken kan man infoga en punkt i det reguljära uttrycket. En punkt matchar ett godtyckligt tecken. Om vi vill söka efter alla förekomster av två e som har exakt ett godtyckligt tecken mellan sig kan vi alltså göra så här:
turte123@li10-3:-$ grep e.e resultat2.txt
Peter Bajramovic 20 9 12
Johan Seeger 13 16 9
Therese Nilsson 15 15 7
Om vi vill söka efter specifika tecken kan vi tala om vilka som ska matchas genom att omge dem med hakparenteser
[...]
.
Varje uppsättning hakparenteser matchar exakt ett av de tecken som räknas upp mellan parenteserna. Vi kan söka efter alla namn som har en sekvens som börjar med versalt eller gement
A
eller
E,
följs av två
n
och avslutas med
a
eller
e
på följande sätt:
turte123@li10-3:-$ grep "[AaEe]nn[ae]" resultat2.txt
Annette Sundman 20 19 21
Johanna Tuhkunen 22 9 11
Hannes Olsson 16 8 10
Johanna Dahlerup 7 10 22
Anneli Eliasson 8 22 11
Här måste vi omge mönstret med citattecken för att inte vårt skal ska misstolka hakparenteserna. Inom hakparentserna kan vi också ange intervall av tecken. Mönstret
[a-k]
matchar alla små bokstäver från
a
till
k.
Intervall ska dock användas med viss försiktighet eftersom de är beroende av vilka språkinställningar man har. Det är inte säkert att
[a-ö]
ger det resultat man förväntar sig. Dock kan vi lokalisera alla som har något resultat 20-29 genom att söka på följande sätt:
turte123@li10-3:-$ grep "2[0-9]" resultat2.txt
Peter Bajramovic 20 9 12
Per Karlsson 21 - 21
Engla Hedberg 21 11 21
...
Övning
Vilka personer, i båda filerna, har namn som innehåller kvist eller qvist?
Lösningsförslag
Övning
Vilka personer, i båda filerna, har enbart udda resultat i alla tre kolumnerna?
Lösningsförslag
Konstruktion av reguljära uttryck
I detta avsnitt visar vi hur man kan sätta samman reguljära uttryck för att söka efter mer komplicerade mönster.
Upprepning
Genom att placera en asterisk
*
efter en del av ett reguljärt uttryck talar man om att denna del kan förekomma godtyckligt många gånger (noll, en eller flera). Asterisken kan t.ex. sättas efter en enstaka bokstav, efter en punkt eller efter ett par hakparenteser. Vi kan söka efter namn som någonstans har ett stort
A
följt av godtyckliga tecken och därefter ett litet
n
på följande sätt:
turte123@li10-3:-$ grep "A.*n" resultat2.txt
Annette Sundman 20 19 21
Jonas Andersson 11 12 12
Ann Nordenberg 17 14 14
Arten Wärn 19 10 -
Anneli Eliasson 8 22 11
Vårt problem från början av avsnittet, att hitta alla stavningar av Karlsson, kan nu lösas:
turte123@li10-3:-$ grep "[CK]arls*z*on" resultat1.txt resultat2.txt
resultat1.txt:Gustaf Karlsson 12 14 13
resultat1.txt:Marcus Carlsson 12 9 12
resultat1.txt:Josefine Carlson 18 14 16
resultat1.txt:Mats Karlzon 15 17 10
resultat2.txt:Per Karlsson 21 - 21
Vi söker här efter sekvenser som inleds med C eller K, fortsätter med arl och därefter har godtyckligt många s följt av godtyckligt många z avslutat med on.
Förankring
Om man vill söka efter något som finns i början eller slutet av raden kan man använda förankringstecknen
^
eller
$
.
Vi kan söka efter alla som har förnamn som börjar på
E
på följande sätt:
turte123@li10-3:-$ grep ^E resultat2.txt
Engla Hedberg 21 11 21
Erik Hernqvist 7 7 9
Om vi inte hade använt förankringstecknet hade vi fått träffar även på personer vars efternamn börjar på E. Genom att kombinera förankringstecknen kan vi söka efter kompletta rader, t.ex. kan vi räkna alla tomma rader så här:
turte123@li10-3:-$ grep -c ^$ resultat2.txt
0
Alternativ
Denna genomgång har hittills handlat om grundläggande reguljära uttryck. Det finns också en utökad variant. Normalt klarar man sig bra med enbart grundläggande reguljära uttryck, men en aspekt av den utökade varianten är att man på ett lätt sätt kan ange alternativ.
För att kunna använda utökade reguljära uttryck måste man använda kommandot
egrep
istället. Det fungerar som
grep
med skillnaden att det finns fler möjligheter att konstruera reguljära uttryck. Olika alternativ separeras med pipetecken
|
och vi kan t.ex. söka efter personer som har ett förnamn som börjar på
S
eller ett efternamn som börjar på
F
så här:
turte123@li10-3:-$ egrep "^S| F" resultat1.txt
David Fors 8 12 11
Siv Tidblom 11 9 12
Undantag
Hur gör man om man vill söka efter något av de tecken som används för att konstruera reguljära uttryck? Alla sådana tecken som ska tolkas bokstavligt måste ha ett bakåtvänt snedstreck framför sig. Vill man söka efter en asterisk skriver man alltså
\*
.
Övningar
Övning
Vilka personer, i båda filerna, har namn som slutar på a?
Lösningsförslag
Övning
Vilka personer, i båda filerna, har ett förnamn som består av exakt tre bokstäver?
Lösningsförslag
Övning
Hur många av de personer, i båda filerna, som heter Johan i förnamn har resultat i alla tre kolumnerna?
Lösningsförslag
Sammanfattning
Denna genomgång tar inte upp alla aspekter av reguljära uttryck. Titta gärna i manualsidorna för
grep
,
egrep
eller
regexp
om du vill veta mer. Det kan också vara värt att notera att andra varianter av Linux kan ha andra varianter av
grep
.
Följande tabell sammanfattar vad vi gått igenom och vad som gäller när du arbetar på IDA:
Mönster | Förklaring |
---|---|
. |
matchar exakt ett godtyckligt tecken |
[ ] |
matchar exakt ett tecken som räknats upp inom klamrarna |
m* |
matchar mönstret m noll, en eller flera gånger |
^ |
matchar början av raden |
$ |
matchar slutet av raden |
m1|m2 |
matchar endera av mönstren m1 eller m2 (fungerar endast med egrep ) |
\m |
matchar tecknet m som är ett av de specialtecken som normalt används för att bygga upp reguljära uttryck |
Följande flaggor kan användas till grep:
Flagga | Betydelse |
---|---|
-i |
Gör ingen skillnad på små och stora bokstäver |
-v |
Sök efter rader som inte matchar det givna ordet |
-w |
Sök efter den angivna texten som ett ord, dvs det måste finnas avgränsning runt ordet |
-n |
Skriv ut radnummer för alla rader som hittas |
-c |
Skriv enbart ut antalet hittade rader, inte raderna i sig |
Diagnos
När du har läst detta avsnitt är det dags att göra diagnos D13. Reguljära uttryck . Gå till kursrummet i Lisam och klicka på Test i vänstermenyn.
Viktigt
Innan du ger dig på diagnosen ska du spara filen
lista4.txt
som du kommer använda under diagnosen för att svara på frågor. Både namn och personnummer i filen är slumpmässigt valda och har ingenting med verkligheten att göra.
Universitetsparken erbjuder lugn och ro
Sidansvarig: Peter Dalenius
Senast uppdaterad: 2024-08-26