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