Quel poco che so di Perl - 4.4
Ven, 17 Febbraio 2006 - 12:01
Inviato da: marcocoisson
Le regular expression, come abbiamo visto, possono essere usate per individuare in una stringa la presenza di un pattern anche molto complicato. Spesso, però, individuare il pattern è solo metà del lavoro: con esso si vogliono poi effettuare specifiche operazioni, che dipendono naturalmente dallo scopo del programma che stiamo realizzato. Se l'operazione richiesta è di sostituzione, Perl ci viene incontro con una serie di costrutti già pronti per l'uso, e che vedremo brevemente in questa puntata.
Aprite il vostro editor di testo preferito e digitate il seguente codice:
#!/usr/bin/perl
while(<>)
{
s/e/3/;
print $_;
}
Salvatelo col nome che volete, rendetelo eseguibile, ed eseguitelo. Senza tanti preamboli, il programma si aspetta che voi digitiate una riga di testo, quindi ve la riproporrà, sostituendo la prima occorrenza della lettera e col numero 3. Com'è possibile questo trucco?
Il segreto sta nell'operatore di sostituzione s///, assolutamente identico all'operatore di ricerca m//, che però ha due argomenti anziché uno: il primo definisce il pattern da individuare nella stringa, il secondo definisce con che cosa sostituirlo. Ecco allora che il significato di s/e/3/ diventa particolarmente semplice:
- all'interno della variabile automatica di ricerca $_ (dal momento che non stiamo usando l'operatore di binding =~, anch'esso utilizzabile con un argomento in più per effettuare sostituzioni), individua il pattern definito dalla regular expression che compare tra la prima coppia di delimitatori // (in questo caso la regular expression è molto semplice e consiste nella sola lettera e);
- sostituisce quindi il pattern individuato al passaggio precedente con quello specificato dalla regular expression presente tra la seconda coppia di delimitatori // (in questo caso il numero 3).
Quindi, mediante l'istruzione print, il programma riscrive la riga di testo che noi gli avevamo dato in pasto, con la sostituzione effettuata.
Il comportamento di questo programma è interessante, perché possiamo fare vari tentativi in condizioni diverse:
- se l'input è Cesana la risposta, come ci aspettiamo, è C3sana;
- ma se l'input è Sestriere, la risposta è S3striere; la ragione, in realtà, già la sappiamo: tutti questi operatori di matching e di sostituzione individuano solo la prima occorrenza del pattern specificato all'interno della stringa su cui si effettua la ricerca.
In passato abbiamo ovviato al problema usando le variabili automatiche $`, $& e $' per spezzare la stringa su cui effettuare la ricerca e proseguire, in un ciclo, fino al termine di essa. Ma in realtà c'è un modo più comodo per fare tutto questo, che consiste nell'usare un apposito modificatore da applicare all'operatore di ricerca o di sostituzione. Modifichiamo pertanto la riga contente l'operatore s/// con la seguente:
s/e/3/g;
L'aggiunta del modificatore g alla fine indica che vogliamo effettuare una ricerca (nel caso dell'operatore m//) o una sostituzione (nel caso dell'operatore s///) globale, su tutta la stringa. Ecco allora che il nostro programma reagirà in maniera differente all'input: Cesana sarà sempre modificato in C3sana, ma Sestriere ora diventerà S3stri3r3. È interessante notare come Empedocle diventerà Emp3docl3, perché la regular expression usata per la ricerca individua la sola lettera e minuscola. Possiamo effettuare la sostituzione anche alla lettera E maiuscola? Naturalmente sì, e abbiamo due modi per farlo. Il primo, ovvio, è quello di modificare la regular expression:
s/e|E/3/g;
cercherà l'occorrenza di tutte (grazie al modificatore g) le lettere e oppure E, sostituendole con il numero 3; e ovviamente questo metodo funziona. Ma un altro modificatore, i che sta per (case) insensitive, ovvero "insensibile a maiuscole/minuscole", raggiunge lo stesso scopo:
s/e/3/gi;
Notate che abbiamo usato due modificatori, g e i, semplicemente mettendoli uno in fila all'altro. In entrambi i casi, Empedocle viene modificato in 3mp3docl3.
Quando si effettuano sostituzioni mediante l'operatore s/// (o l'equivalente =~ /// se si vuole usare una variabile diversa da $_) è possibile usare alcuni altri modificatori che agiscono, a differenza di quelli visti in precedenza, sulla sola regular expression usata per la sostituzione. Modifichiamo ad esempio il programma alterando ancora una volta la riga contenente l'operatore s///:
s/^(.)/\U$1/;
Che cosa fa questo costrutto particolare? Analizziamolo nel dettaglio:
- la regular expression usata per la ricerca è ^(.): ovvero essa individua il primo carattere della riga di testo che abbiamo digitato, qualunque esso sia;
- poiché esso è racchiuso tra parentesi tonde, esso sarà memorizzato nella variabile automatica $1;
- possiamo usare questa variabile automatica già all'interno della regular expression usata per la sostituzione; facendola precedere da \U chiediamo che questo carattere contenuto in $1 sia sostituito dalla sua variante maiuscola (U sta per uppercase).
Così pippo viene sostituito con Pippo, Arsenio viene lasciato inalterato in Arsenio, e *13d5, iniziando con un carattere che non è una lettera dell'alfabeto (e che quindi non ha una variante maiuscola) viene lasciato anch'esso inalterato. L'analogo di \U per trasformare il carattere in una lettera minuscola è \L (dove L sta per lowercase).
Siccome, come ormai avete imparato, in Perl c'è sempre più di un modo per fare le cose, possiamo ottenere lo stesso scopo (mettere maiuscola la prima lettera della riga di testo digitata) ad esempio con quest'altra modifica al codice:
s/^(\w)/\u$1/;
Questa volta, anziché cercare il primo carattere, individuiamo la prima parola (mediante \w), la memorizziamo in $1 grazie alle parentesi tonde, e la riproponiamo nella regular expression di sostituzione preceduta da \u, che differisce da quella usata precedentemente per il fatto che la u ora è minuscola anziché essere maiuscola; questa differenza indica quanto segue:
- \U e \L agiscono su tutto quanto segue;
- \u e \l agiscolo solo sul primo carattere di quanto segue.
In entrambi i casi, il risultato è che pippo viene convertito in Pippo, tanto per fare un esempio.
L'argomento delle regular expression è ancora vasto, e potrebbe costituire da solo l'oggetto di un libro intero. In questo nostro piccolo corso terminiamo qui la trattazione sistematica delle regular expression, che comunque useremo ancora in futuro, iniziando, con la prossima puntata, ad occuparci di un nuovo, importante argomento.
0 commenti
http://www.tevac.com/article.php/20060217120137586