Le espressioni regolari sono uno strumento fondamentale per la gestione del testo, e uno dei linguaggi che ha fatto di questo strumento un punto di forza è sicuramente il Perl. Il Ruby, che nelle idee di Matz nasce come suo naturale erede, non poteva non avere un supporto alle espressioni regolari altrettanto potente.
Brevemente, rimandando a testi appositi una trattazione più approfondita, possiamo dire che le espressioni regolari vengono utilizzate per controllare se una stringa verifica un certo schema (pattern). O in altre parole, le espressioni regolari, forniscono dei modelli per ricercare all'interno di un testo non solo utilizzando espressioni letterali ma anche particolari identificatori che rappresentano delle determinate classi di caratteri.
In Ruby sono oggetti della classe Regexp
che possono essere creati, come gli Array e gli Hash, in diversi modi. Si può utilizzare il metodo new
di Regexp
:
expr = Regexp.new('')
passando come argomento l'espressione regolare vera e propria, oppure racchiudendola tra due / ('slash'):
expr = //
o ancora utilizzando %r
:
expr = %r{}
Una volta creata la nostra espressione regolare possiamo confrontarla con qualsiasi stringa utilizzando il metodo match della classe Regexp
oppure l'operatore =~
e il suo negato !~
. Ad esempio:
> er = Regexp.new('sw+') => /sw+/ > stringa = "Ciao mondo" => "Ciao mondo" > stringa =~ er => 4 > $&m => " mondo" > $` => "Ciao"
=~
restituisce la posizione del primo carattere che verifica l'espressione regolare mentre le variabili speciali $&
e $`
rappresentano rispettivamente la parte di stringa che verifica il pattern e la parte che non lo verifica.
Come già detto, all'interno di una espressione regolare oltre ai normali caratteri è possibile usare delle sequenze che rappresentano delle determinate classi, in Tabella1 c'è un elenco completo. In alternativa è possibile creare delle classi racchiudendo i caratteri tra parentesi quadre, ad esempio [A-Za-z]
sta a indicare tutte le lettere dalla a alla z sia maiuscole che minuscole.
. | un carattere qualsiasi |
w | lettera o numero, come [0-9A-Za-z] |
W | il contrario di w, ne' lettera ne' cifra |
s | spazio (spazio vero e proprio, tabulazione e carattere di fine riga), come [tnrf] |
S | carattere non spazio |
d | cifra numerica, come [0-9] |
D | il contrario di d, carattere non numerico |
b | backspace se si trova in una specifica di intervallo |
b | limite di parola |
B | non limite di parola |
Oltre ai caratteri in una espressione regolare è possibile anche utilizzare due particolari elementi, ^
('accento circonflesso') e $
('dollaro'), che indicano una precisa posizione del testo cercato. ^
va usato se i caratteri cercati si devono trovare all'inizio del testo, $
se si devono trovare alla fine. Ci sono quindi i simboli quantificativi:
* | zero o più ripetizioni del carattere precedente |
+ | una o più ripetizioni del carattere precedente |
{m,n} | almeno m e massimo n ripetizioni del carattere precedente |
? | al massimo una ripetizione del precedente; lo stesso che {0,1} |
Abbiamo poi |
('pipe') che rappresenta il meccanismo dell'alternanza che permette di definire più alternative. Ad esempio /http|ftp|smtp/
permette di trovare una delle corrispondenze indicate nell'espressione. Infine, come è consueto, è possibile catturare una parte della stringa verificata in modo da utilizzarla sia all'interno del pattern stesso, riferendoci ad essa con 1
, 2
e così via, sia all'esterno utilizzando le variabili speciali $1
, $2
ecc. Ad esempio volendo catturare la parola "mondo" dell'esempio precedente dobbiamo scrivere:
> er = Regexp.new('s(w+)') => /s(w+)/ > stringa = "Ciao mondo" => "Ciao mondo" > stringa =~ er => 4 > $1 => "mondo"