Poniamo di definire la seguente stringa:
$a = 'Ho comprato 2 rose nere';
e che il numero di rose possa variare indefinitamente. Quello che desideriamo è far sì che il matching abbia esito positivo solo se le rose comprate sono due oppure tre. La soluzione al problema potrebbe essere la seguente:
$a =~ /^Ho comprato (2|3) rose nere$/;
É tuttavia possibile ricorrere alla classi di caratteri, che come vedremo tra poco costituiscono una soluzione ben più completa a problemi di questo tipo:
$a =~ /^Ho comprato [23] rose nere$/;
La parte tra parentesi quadre è la classe, ed è costituita dai vari caratteri che dobbiamo considerare validi ai fini del matching, in questo caso 2 e 3. Una classe di caratteri permette anche di specificare un intervallo. Se ad esempio le rose devono essere un numero variabile da tre a otto possiamo utilizzare una qualsiasi delle seguenti tre soluzioni:
# Senza classe di caratteri
$a =~ /^Ho comprato (3|4|5|6|7|8) rose nere$/;
# Con classe di caratteri senza intervallo
$a =~ /^Ho comprato [345678] rose nere$/;
# Con classe di caratteri ed intervallo
$a =~ /^Ho comprato [3-8] rose nere$/;
Appare evidente la maggiore efficienza delle ultime due soluzioni, e la maggiore praticità dell'ultima in particolare. Gli intervalli specificabili sono di vario tipo:
# Cerca un qualsiasi numero in $a
$a =~ /[0-9]/;
# Cerca una qualsiasi lettera minuscola in $a
$a =~ /[a-z]/;
# Cerca una qualsiasi lettera maiuscola in $a
$a =~ /[A-Z]/;
In una classe si possono tranquillamente combinare più intervalli, mescolandoli anche a caratteri singoli. Se ad esempio poniamo un generico (e fin troppo semplice) codice di registrazione di un programma:
$a = 'REGt';
e vogliamo verificare che l'ultimo carattere sia compreso tra a e c, F e M oppure sia t o ancora un numero fra 3 e 7 possiamo usare:
$a =~ /^REG[a-cF-M3-7t]$/;
Ogni classe di caratteri può avere significato sia negativo che positivo. Se infatti il nostro desiderio è che l'ultimo carattere del codice non sia uno di quelli sopra citati possiamo senz'altro utilizzare:
$a !~ /^REG[a-cF-M3-7t]$/;
L'operatore !~ ribalta il significato logico di ogni pattern matching: esso differisce da =~ allo stesso modo in cui != differisce da ==. Potremmo comunque ometterne l'uso cambiando direttamente il significato della classe di caratteri:
$a =~ /^REG[^a-cF-M3-7t]$/;
L'accento circonflesso (^, chiamato informalmente anche coppo) corrisponde ad un not, e quindi indica alla regular expression di trovare caratteri che non siano quelli che lo seguono all'interno della classe. É molto importante distinguere i due diversi significati dell'accento circonflesso: se è posto all'inizio della regular expression esso fa sì che il matching abbia inizio con il primo carattere della stringa e mai dopo; se invece il suo contesto è rappresentato da una classe di caratteri, esso ne ribalta il significato. I quantificatori possono essere associati alle classi esattamente come lo sono ai caratteri normali:
$a =~ /^Ho comprato [0-9]+ rose nere$/;
Questa regular expression ha esito positivo se il numero di rose è un qualsiasi intero positivo maggiore o uguale a zero: la classe di caratteri è infatti ripetibile, per via del quantificatore +, un numero arbitrario di volte. Potremmo ulteriormente raffinare la nostra espressione così:
$a =~ /^Ho comprato [1-9][0-9]* rose nere$/;
La differenza con l'esempio precedente è che in questo caso la prima cifra (che può anche essere l'unica) deve essere un numero da uno a nove: non è quindi possibile evitare di acquistare almeno una rosa nera!
|