Göm menyn

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

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: 2023-08-21