Espressioni regolari - home page luca orrù

Transcript

Espressioni regolari - home page luca orrù
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Espressioni regolari
Le espressioni regolari sono usate per la ricerca di stringhe di testo
all’interno di un file di testo. Si possono trovare le espressioni regolari in
editor di testo come l’editor vi, oppure in programmi come grep, egrep, e
in linguaggi come awk o perl. Noi ci occuperemo principalmente dell’uso
delle espressioni regolari attraverso grep, egrep e awk. L’uso delle
espressioni regolari per revisioni di testo con vi è descritto nella relativa
dispensa.
Una espressione regolare è una sequenza di caratteri, combinati in modo
opportuno, che costituiscono un modello di ricerca che viene confrontato
con la stringa di testo da ricercare all’interno del file di testo specificato.
Il modello di ricerca è simile per grep, egrep e awk con qualche piccola
differenza.
La sintassi del comando grep è la seguente:
grep ‘modello di ricerca’ nomefile
Esistono dei caratteri speciali che possono essere usati nel modello di
ricerca.
Operatori di ripetizione
Un carattere singolo può essere da uno dei seguenti operatori di ripetizione
* identifica da 0 a n ripetizioni del carattere precedente all’ * (0 o più
volte).
+ identifica da 1 a n ripetizioni del carattere precedente (1 o più volte).
{n} identifica esattamente n ripetizioni del carattere precedente.
{1,} identifica da 1 a n ripetizioni del carattere precedente.
{n,} identifica almeno n ripetizioni (n o più ripetizioni) del carattere
precedente.
{n,m} identifica da n a m ripetizioni del carattere precedente (almeno n
ma non più di m).
{ ,m} identifica al massimo m ripetizioni del carattere precedente.
Autore: Luca Orrù
1
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Intervalli
[a-z] specifica uno qualsiasi dei caratteri compresi tra a e z.
[A-Z] specifica uno qualsiasi dei caratteri compresi tra A e Z.
[0-9] specifica una qualsiasi delle cifre comprese tra 0 e 9.
Memoria
Le parentesi tonde ( ) fanno memorizzare il testo incluso al loro interno.
Esempio:
\( [0-9] *\) memorizza la sequenza di n cifre con n>=0
Per richiamare il contenuto memorizzato si usa : \1
Se ci sono più stringhe memorizzate allora si devono usare \2, \3 etc per
richiamare rispettivamente la seconda variabile, la terza e cosi via.
La parentesi tonda è un carattere speciale e deve essere sempre preceduta
dal carattere di escape \.
Come già detto precedentemente, per indicare la ripetizione di un
particolare carattere alfanumerico si può usare anche \{1, \ } che indica 1 o
più volte.
Poiché la parentesi grafa è un carattere speciale, deve essere sempre
preceduta dal simbolo di escape \ . Il simbolo di escape permette di
interpretare un carattere speciale come tale.
Le parentesi tonde e grafe sono caratteri speciali.
Se non si usa il carattere di escape \ prima della tonda e prima della grafa
allora queste ultime farebbero parte della stringa da ricercare.
Un altro carattere molto usato è il carattere punto .
Il punto identifica qualsiasi carattere escluso la new line.
Caratteri di inizio e fine riga
^ identifica l’inizio della riga
$ identifica la fine della riga
Per comprendere l’argomento svolgiamo tutti gli esercizi finora proposti
nelle prove d’esame.
Autore: Luca Orrù
2
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Appello del 19/06/2006
Esercizio 6. Dato il file nomi.txt strutturato nel seguente modo:
3412 Bob
3834 Jonny
1248 Kate
1423 Tony
2567 Peter
3567 Alice
1548 Kerry
123
333
634
567
435
535
534
scrivere il comando Unix (espressione regolare) che permetta di
trovare:
1. Tutte le righe che finiscono con una cifra nell’intervallo [5-9]
2. Tutte le righe il cui nome inizi con la sequenza “Al”
3. Tutte le righe che iniziano con un codice minore di 5000
4. Tutte le righe che finiscono con un codice che ha tutte e tre le
cifre uguali (ad esempio: 333, 555, etc)
1.
dalla linea di comando (terminale) dopo il prompt digitare:
grep ‘[5-9]$’ nomi.txt
tutto ciò che sta dentro le virgolette semplici costituisce il modello di
ricerca. In questo caso:
[5-9] identifica una cifra compresa tra 5 e 9 (cerca 5 o 6 o 7 o 8 o 9)
il simbolo di $ identifica la fine della riga;
dopo le virgolette specifico il nome del file all’interno del quale fare la
ricerca;
Autore: Luca Orrù
3
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
2.
Dal prompt digitare:
grep ‘Al’ nomi.txt
oppure più correttamente:
grep ‘^[0-9]* Al’ nomi.txt
cerca le righe che iniziano con una cifra, ripetuta almeno 0 volte e seguita
da uno spazio. Dopo lo spazio la riga deve continuare con la sequenza Al.
* specifica una ripetizione da 0 a n volte.
^ specifica l’inizio di una riga
Con awk abbiamo
awk ‘/Al*/{print $0}’ nomi.txt
oppure
awk ‘/Al/{print $0}’ nomi.txt
$0 permette di stampare tutta la riga che soddisfa la condizione di ricerca
3.
grep ‘^[0-4][0-9][0-9][0-9]’ nomi.txt
la prima cifra deve essere compresa tra 0 e 4 e quindi devo specificare per
la prima cifra un intervallo tra 0 e 4.
Le altre tre cifre possono andare da 0 a 9.
Soluzioni alternative:
grep ‘^[0-4][0-9]\{0,2\}’ nomi.txt
cerca un codice che inizia con una cifra compresa tra 0 e 4 a cui segue una
qualunque altra cifra ripetuta da un minimo di 0 volte ad un massimo di 2
Autore: Luca Orrù
4
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
volte. In questo modo generalizzo al caso di codici con un numero di cifre
inferiore a 4 (per esempio codici con 1,2 o 3 cifre).
Esempio: 200 è un codice inferiore a 5000 e quindi deve essere trovato.
grep ‘^[0-4]\{1,3\}’ nomi.txt
4.
grep ‘\([0-9]\)\1\1$’ nomi.txt
le parentesi tonde permettono di memorizzare il valore racchiuso al loro
interno. Nel nostro caso viene memorizzata la prima cifra del codice
finale. Poiché la parentesi è un carattere speciale e come tale deve essere
considerato, allora devo far precedere le parentesi tonde dal carattere di
escape \. Si veda anche espressioni regolari con vi.
\1 è una variabile che contiene il valore memorizzato. Se quindi il valore
memorizzato era 3 allora \1 contiene 3 e quindi basta richiamarlo due
volte ed aggiungerlo alla prima cifra del codice finale per far in modo che
sia ricercato un codice con tutte e tre le cifre uguali.
Con egrep si ha una piccola differenza
egrep ‘([0-9])\1\1$’ nomi.txt
le parentesi non sono precedute dal carattere di escape \.
Autore: Luca Orrù
5
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Appello del 13/09/2005
Esercizio 6. Dato il file nomi.txt strutturato nel seguente modo:
3412 Bob
3834 Jonny
1248 Kate
1423 Tony
2567 Peter
3567 Alice
1548 Kerry
123
333
634
567
435
535
534
scrivere le espressioni regolari che permettono di trovare:
1. Tutte le righe che iniziano nell’intervallo [23-29]
2. Tutte le righe che hanno come primo e ultimo carattere un ‘1’
3. Tutte le righe che iniziano con un carattere che non sia un ‘1’ e
non sia un ‘9’
4. Tutte le righe che terminano con un codice palindromo
Tra i codici numerici iniziali e i nomi c’è uno spazio
1.
grep ‘^2[3-9]’ nomi.txt
cerca tutte le righe che hanno 2 come cifra iniziale a cui segue una
qualunque cifra compresa tra 3 e 9 con 3 e 9 inclusi.
2.
grep ‘^1.*1$’ nomi.txt
^1 identifica tutte le righe che iniziano con 1
. identifica qualsiasi carattere successivo alla cifra 1
* dice che il carattere identificato da punto può ripetersi da 0 o più volte
1$ dice che la riga deve terminare con la cifra 1
Autore: Luca Orrù
6
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
3.
grep ‘^[^19]’ nomi.txt
il simbolo di ^ all’interno delle quadre esclude i caratteri specificati nelle
quadre.
Esempio:[^2-7] ricerca tutti i caratteri che non siano 2 3 4 5 6 7.
4.
grep ‘\([0-9]\).\1$’ nomi.txt
memorizzo la prima cifra del codice finale con \([0-9]\)
il punto identifica poi qualsiasi altra cifra
infine richiamo la cifra iniziale con \1
alternative
grep ‘\([0-9]\)[0-9]\1$’ nomi.txt
egrep‘([0-9])[0-9]\1$’ nomi.txt
Autore: Luca Orrù
7
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Appello del 23/01/2004
Esercizio 6. Dato il file nomi.txt strutturato nel seguente modo:
3412 Bob
3834 Jonny
1248 Kate
1423 Tony
2567 Peter
3567 Alice
1548 Kerry
123
333
634
567
435
535
534
scrivere le espressioni regolari che permettono di trovare:
1. Tutte le righe che finiscono nell’intervallo [3-7]
2. Tutte le righe il cui nome inizi con la sequenza ‘Pe’
3. Tutte le righe che iniziano con un codice maggiore di 4999
4. Tutte le righe che terminano con un codice che ha come prima e
ultima cifra un 5
Tra i codici numerici iniziali e i nomi c’è uno spazio
1.
grep ‘[3-7]$’ nomi.txt
2.
grep ‘Pe’ nomi.txt
oppure
grep ‘^[0-9][0-9]*_Pe’ nomi.txt
_ significa spazio
Autore: Luca Orrù
8
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
3.
grep ‘^[5-9][0-9][0-9][0-9]’ nomi.txt
oppure
grep ‘ ^[5-9][0-9]\{2,\}’ nomi.txt
generalizza al caso di codice con un numero di cifre maggiore di 4
Infatti {2,\} specifica 2 o più volte
4.
grep ‘5.5$’ nomi.txt
oppure
grep ‘5[0-9]5$’ nomi.txt
caso di n cifre finali con n >=2
grep ‘5[0-9]*5$’ nomi.txt
Autore: Luca Orrù
9
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Appello del 12/05/2004
Esercizio 6. Dato il file nomi.txt strutturato nel seguente modo:
3412 Bob
3834 Jonny
1248 Kate
1423 Tony
2567 Peter
3567 Alice
1548 Kerry
123
333
634
567
435
535
534
scrivere le espressioni regolari che permettono di trovare:
1. Tutte le righe che iniziano con una cifra nell’intervallo [1-3]
2. Tutte le righe il cui nome termini con la sequenza ‘er’
3. Tutte le righe che finiscono con un codice maggiore di 450
4. Tutte le righe che iniziano con un codice che ha come prima e
ultima cifra un 5
Tra i codici numerici iniziali e i nomi c’è uno spazio
1.
grep ‘^[1-3]’ nomi.txt
2.
grep ‘.*er\>’ nomi.txt
\> identifica il termine della stringa di ricerca cioè la stringa deve fin]ire
in er
.* qualsiasi carattere ripetuto 0 o più volte
Autore: Luca Orrù
10
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
oppure
grep ‘[0-9][0-9][0-9][0-9]_[A-Z][a-z]*er\>’ nomi.txt
grep ‘[0-9][0-9]*_[A-Z][a-z]*er\>’ nomi.txt
grep ‘[0-9]\{1,\}_.\{1,\}er\>’ nomi.txt
qualsiasi cifra, ripetuta almeno 1 volta seguita da uno spazio e da un
qualsiasi carattere. Il carattere deve comparire 1 o più volte. Alla fine di
questa sequenza ci deve essere er.
Con awk
awk ‘/.*er\>/ {print$0}’ nomi.txt
3.
esercizio bastardo!
awk ‘ /[4-9][5-9][1-9]$||[5-9][0-5][0-9]$/ {print$0}’ nomi.txt
|| è l’operatore di OR logico
/[4-9][5-9][1-9]$ scrivendo solo questo pattern il comando non trova tutti i
codici maggiori di 450 ma solo alcuni e precisamente esclude tutti i codici
compresi tra:
500-550
600-650
700-750
800-850
900-950
Il secondo pattern messo in OR con il primo pattern consente di trovare
questi codici che il primo pattern non trova.
Autore: Luca Orrù
11
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Se qualcuno riesce a farlo con grep me lo segnali.
4.
grep ‘^5[0-9][0-9]5’ nomi.txt
oppure
grep ‘^5..5\>’ nomi.txt
più in generale
grep ^5[0-9]*5\> nomi.txt
awk ‘/^5.*5\> {print$0}’ nomi.txt
Autore: Luca Orrù
12
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Appello del 19/12/2003
Esercizio 6. Dato il file nomi.txt strutturato nel seguente modo:
3412 Bob
3834 Jonny
1248 Kate
1423 Tony
2567 Peter
3567 Alice
1548 Kerry
123
333
634
567
435
535
534
scrivere le espressioni regolari che permettono di trovare:
1. Tutte le righe che iniziano con una cifra nell’intervallo [3-7]
2. Tutte le righe che hanno come primo carattere un ‘1’ e come
secondo carattere una cifra nell’intervallo [0-4]
3. Tutte le righe che iniziano con un carattere che non sia un ‘1’
4. Tutte le righe che iniziano con un codice palindromo
1.
grep ‘^[3-7]’ nomi.txt
2.
grep ‘^1[0-4]’ nomi.txt
3.
grep ‘^[^1]’ nomi.txt
4.
egrep ‘^([0-9]) ([0-9])\2\1’ nomi.txt
la variabile 1 (\1) contiene la prima cifra
la variabile 2 (\2) contiene la seconda cifra
Autore: Luca Orrù
13
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
Appello del 19/04/2005
Esercizio 6. Dato il file nomi.txt strutturato nel seguente modo:
Mario
Giovanni
Aldo
Michele
Alice
Maria
Marco
Rossi
Verdi
Serra
Santoro
Chiusano
Buscemi
Fornaio
12567
98456
98734
16091
21210
45734
92034
La prima cifra del codice numerico indica l’edificio in cui la persona
lavora; ad esempio Mario Rossi lavora nell’edificio 1. Scrivere le
espressioni regolari che permettono di:
1. Trovare tutte le persone che lavorano nell’edificio numero 5
2. Trovare tutte le persone che si chiamano Aldo
3. Trovare tutte le persone il cui codice numerico termina con 34
4. Trovare tutte le persone che hanno un codice numerico dispari
5. Trovare tutte le persone il cui nome inizia con una vocale
1.
grep ‘5[0-9][0-9][0-9][0-9]’ nomi.txt
grep ‘5….’ nomi.txt
grep ‘\<5’ nomi.txt
l’uso di grep restituisce però tutta la riga che soddisfa la ricerca
Con awk invece riusciamo ad eliminare il codice numerico.
awk ‘/5…./ {print $1,$2}’ nomi.txt
oppure
awk ‘/5[0-9][0-9][0-9][0-9]/ {print $1,$2}’ nomi.txt
Autore: Luca Orrù
14
Architettura dei Sistemi Operativi
Centro Multimediale Montiferru
2.
awk ‘$1==”Aldo” {print $1,$2}’ nomi.txt
grep Aldo nomi.txt
3.
awk ‘/34$/ {print $1,$2}’ nomi.txt
grep ‘34$’ nomi.txt
restituisce tutta la riga
4.
grep ‘[13579]$’ nomi.txt
restituisce tutta la riga
awk ‘/[13579]$/ {print $1,$2}’ nomi.txt
5.
grep ‘^[AEIOU]’ nomi.txt
restituisce tutta la riga
awk ‘/^[AEIOU]/ {print $1,$2}’ nomi.txt
Autore: Luca Orrù
15