String matching


Una delle più utili funzionalità offerte da Perl è il supporto per la manipolazione di stinghe, basato sull'utilizzo delle espressioni regolari (RE) .


Espressioni Regolari

Una espressione regolare è contenuta tra 'slashes' ed un 'matching' si può verificare mendiante l'operatore =~. Ad esempio, la seguente espressione è vera se la stringa the appare nella variabile $sentence.
$sentence =~ /the/
La RE è 'case sensitive', perciò per il seguente assegnamento alla variabile $sentence
$sentence = "The quick brown fox";
il match verificato prima, ora fallisce. L'operatore !~ è utilizzato per verificare un non-match. Nell'esempio precedente:
$sentence !~ /the/
risulta vero perchè la stringa the non compare in $sentence.


La variabile speciale $_

Si può usare una istruzione condizionale come
if ($sentence =~ /under/)
{
	print "We're talking about rugby\n";
}
che stampa in output un messaggio per i seguenti assegnamenti alla variabile $sentence
$sentence = "Up and under";
$sentence = "Best winkles in Sunderland";
Spesso è molto più semplce assegnare la frase alla variabile speciale $_ che è uno scalare. Infatti, facendo in questo modo, possiamo evitare di usare gli operatori di match e non-match ed ottenere un comportamento equivalente. Ad esempio l'esempio precedente può essere riscritto (più semplicemente) in questo modo:
if (/under/)
{
	print "We're talking about rugby\n";
}
La variabile speciale $_ è il default per molte altre operazioni Perl perciò è utilizzata frequentemente.


Approfondimento sulle RE

In una RE ci sono molti caratteri speciali e sono questi che contribuiscono a renderle un potente strumento (anche se a volte può apparire complicato). Perciò il miglior modo di imparare ad usarle è procedendo per gradi.

Di seguito sono elencati alcuni caratteri speciali per le RE con il relativo significato:

.  # un qualsiasi singolo carattere tranne una nuova_linea

^  # L'inizio di una linea o stringa
$  # La fine di una linea o stringa
*  # Zero o più occorrenze dell'ultimo carattere
+  # Una o più occorrenze dell'ultimo carattere
?  # Zero o una occorrenza dell'ultimo carattere


seguono alcuni esempi. Ricordarsi che è necessario usare gli /.../ slashes.


t.e	# t seguito da qualsiasi altro carattere seguito da e 
	# C'è un match con the
	#                  tre
	#                  tle
	# ma non con   te
	#              tale
^f	# f all'inizio di una linea
^ftp	# ftp all'inizio di una linea 
e$	# e alla fine di una linea
tle$	# tle alla fine di una linea
und*	# un seguito da zero o più caratteri 
	# C'è un match con un
	#                  und
	#                  undd
	#                  unddd (etc)
.*	# Una stringa senza una nuova_linea. Ciò perchè, il
	#  . ha un match con qualsiasi cosa tranne una nuova_linea e
	#  * significa zero o più di questi.
^$	# Una linea vuota.

Ci sono diverse opzioni. Le parentesi quadre sono usate per verificare un match dei caratteri in esse contenuti. All'interno delle parentesi quadre un segno di - indica "tra" e un ^ all'inizio significa "not":

[qjk]     # q oppure j oppure k
[^qjk]    # nessuno tra q, j, k
[a-z]     # qualsiasi carattere compreso tra a e z
[^a-z]    # nessun carattere minuscolo
[a-zA-Z]  # una lettera qualsiasi
[a-z]+    # una qualsiasi sequenza (non vuota) di caratteri minuscoli

A questo punto è il momento di passare a fare degli esercizi! Ciò che segue è presentato a titolo informativo.

Una barra verticale | rappresenta una "or" e le parentesi(...) possono essere usate per raggruppare insieme delle cose:


jelly|cream # jelly oppure cream 

(eg|le)gs	# o eggs oppure legs
(da)+		# o da oppure dada oppure dadada oppure...

Ci sono altri caratteri speciali:


\n		# una nuova linea
\t		# tabulazione
\w		# qualsiasi carattere (parola) alfanumerico
		# Equivale a [a-zA-Z0-9_]
\W		# qualsiasi carattere non alfanumerico.
		# Equivalente a [^a-zA-Z0-9_]
\d		# qualsiasi numero. Equivale a  [0-9]
\D		# qualsiasi carattere non numerico. Equivale a [^0-9]
\s		# Qualsiasi spazio-bianco: spazio,
		# tab, nuova linea, etc
\S		# qualsiasi carattere che non sia uno spazio-bianco
\b		# indica i confini di una  parola (word boundary), solo esternamente alle [] 
\B		# nessun confine di parola (word boundary)

Chiaramente, caratteri come $, |, [, ), \, / possono essere presenti come casi particolari nelle espressioni regolari. Perciò, volendo verificare un match per uno di questi caratteri è necesssario che siano preceduti da uno backslash. Ad esempio:

\|		# Vertical bar
\[		# una parentesi quadra aperta
\)		# una parentesi chiusa
\*		# un asterisco
\^		# un accento circonflesso
\/		# uno slash
\\		# uno backslash
e così via.


Alcuni esempi su REs

Seguono alcuni esempi. Ricordarsi che per usare le stringhe per il matching bisogna racchiuderle tra /.../ slashes

[01]		# Either "0" or "1"
\/0		# una divisione per zero: "/0"
\/ 0		# una divsione per zero con uno spazio bianco: "/ 0"
\/\s0		# una divisione per zero con uno spazio bianco:
		# "/ 0" dove lo spazio potrebbe essere una tab etc.
\/ *0		# una divisione per zero con eventuali spazi:
		#"/0" o"/ 0" o"/  0" etc.
\/\s*0		# una divisione per zero con eventuali spazi bianchi.
\/\s*0\.0*	# come prima, ma con il punto decimale e potrebbero esserci
		# degli 0s dopo. sono accettati
		# "/0." e"/0.0" e"/0.00" etc e
		# "/ 0." e"/  0.0" e"/   0.00" etc.


Esercizio

Prima il programma ha contato le linee non vuote. Provare a modificarlo per far si che conti le linee in cui compare In ogni caso il programma potrebbe stampare ogni linea, ma dovrebbe contare solo quelle che soddisfano i requisiti. Provare ad usare la variabile speciale $_ per evitare di usare l'operatore =~ .