Sono un linguaggio per descrivere la “forma” o la “sintassi” di una stringa (una stringa è un testo qualunque, di qualunque lunghezza, una sequenza di caratteri). Con esso si possono effettuare ricerche, e quindi sostituzioni, molto complesse! Verificare che un testo sia conforme ad alcune caratteristiche e segue una certa sintassi (per esempio verificare se un testo è un indirizzo email o un url valido).
NOTA: talvolta le regex hanno piccole differenze tra un programma e l’altro o tra un linguaggio di programmazione ed un altro ma il loro concetto ed utilizzo resta lo stesso. Noi qui vedremo le regex con il comando ‘sed’.
Questo articolo sulle regexp fa parte di una serie di guide sul mio blog ed è un prerequisito per comprendere a fondo l’uso di sed e awk. Se invece volete un piccolo esempio di cosa si può fare con le regex date un occhiata a questo articolo.
L’articolo verrà aggiornato se le mie conoscenze sull’argomento migliorassero ma lo ritengo già abbastanza completo.
Ogni regex comincia e finisce con il carattere slash (/): così: /regex/. Se il testo contenuto tra i due slash è testo semplice verrà ricercata esattamente quella sequenza di caratteri (distinguendo tra maiuscole e minuscole) ma esistono alcuni caratteri particolari che se inseriti all’interno della regex hanno un significato diverso dal loro simbolo, ne vedremo solo alcuni:
^
« apice » ha due significati: se messo all’inizio della regex impone che la linea cominci con quello che segue l’apice; se usato con le parentesi quadre e messo prima di un carattere significa: tranne il carattere che segue, è una negazione$
« dollaro » se messa alla fine della regex impone che la linea finisca con quello che precede il dollaro.
« punto » qualunque carattere*
« asterisco » accetta zero o più ripetizioni del carattere precedente+
« più » accetta una o più ripetizioni del carattere precedente[ ]
« parentesi quadre » tutti i caratteri all’interno delle [ ] sono accettati: le due parentesi si comportano come un singolo carattere- [^ ] « parentesi quadre con apice » tutti i caratteri tranne quelli all’interno delle [ ] sono accettati
/
« slash » inizia/termina l’espressione regolare\
« barra rovesciata » tratta il carattere speciale che segue come un normale carattere testuale o viceversa tratta un normale carattere come un carattere speciale
Esistono poi delle speciali classi di caratteri: sono comode e vale la pena utilizzarle! Eccole qui:
[:alpha:]
« tutte le lettere dalla ‘a’ alla ‘z’ sia maiuscole che minuscole e comprese quelle accentate[:lower:]
« tutte le lettere dalla ‘a’ alla ‘z’ minuscole, comprese quelle accentate[:upper:]
« tutte le lettere dalla ‘A’ alla ‘Z’ maiuscole, comprese quelle accentate[:digit:]
« tutti i numeri (da ‘0’ a ‘9’)[:alnum:]
« come [:alpha:] e [:digit:] insieme: tutti i numeri e tutte le lettere sia maiuscole che minuscole[:space:]
« spazi[:blank:]
« spazi e tab[:cntrl:]
« caratteri di controllo: sono tutti quei caratteri che non si possono stampare come il “fine riga”[:print:]
« opposto di [:cntrl:]: tutti i caratteri che non sono caratteri di controllo[:print:]
« tutti i caratteri visibili, quindi ad esempio gli spazi sono esclusi, la punteggiatura è inclusa ecc…[:punct:]
« tutti i caratteri di punteggiatura[:xdigit:]
« corrisponde al carattere [0-9a-fA-F]: cioè tutti i caratteri che possono formare un numero esadecimale (da 0 [zero] ad F)
Le classi di caratteri si usano come fossero dei caratteri e quindi vanno indicate così: [[:alpha:]] all’interno di altre parentesi quadre
Ora vediamo qualche esempio di regex:
/./
« corrisponde a qualunque linea che contiene almeno un carattere/../
« corrisponde a qualunque linea che contiene almeno due caratteri/^#/
« corrisponde a qualunque linea che comincia con il carattere # (cancelletto)/^$/
« corrisponde a qualunque linea vuota 🙂/}$/
« corrisponde a qualunque linea finisca con ‘}’/} *$/
« corrisponde a qualunque linea finisca con una ‘}’ seguita da zero o più spazi (nota che c’è uno spazio tra la graffa e l’asterisco, quindi l’asterisco agisce sullo spazio)/[abc]/
« corrisponde a qualunque riga contenga anche uno solo tra i caratteri ‘a’, ‘b’, o ‘c’ minuscoli/^[abc]/
« corrisponde a qualunque riga cominci con ‘a’, ‘b’, o ‘c’ minuscoli- /^ciao$/ « corrisponde a linee che contengono la sola parola “ciao” tutta in minuscolo, e nient’altro
- /^[Cc]iao/ « corrisponde a tutte le linee che cominciano con “ciao” o “Ciao”
- /^[Cc]iao+$/ « corrisponde a tutte le righe che contengono la sola parola “ciao” con iniziale maiuscola o minuscola e qualunque numero di “o” finali, ma almeno una (es. “Ciaoooo”, “ciao”, “ciaooo”. La parola “cia” è scartata)
/Eh[eh]*/
« corrisponde a tutte le righe che contengono “Eh” seguita da un qualunque numero e combinazione di lettere ‘e’ ed ‘h’ (es. “Eheheheh”, “Ehhehhheeehehe”, “Eh”, “anchEhcosì”)/^[a-z]+$/
« corrisponde a qualunque riga composta da sole lettere minuscole, senza numeri o simboli ma almeno 1 carattere ( [a-z] = caratteri dalla ‘a’ alla ‘z’); attenzione perché le lettere accentate sono escluse/^[A-Za-z]+$/
« come il precedente ma accetta anche le maiuscole/^[0-9]+$/
« come il precedente ma con solo numeri/^a\{6\}$/
« corrisponde alla sola riga “aaaaaa”, significa che il carattere ‘a’ dev’essere ripetuto 6 volte. Le parentesi graffe sono precedute dal carattere speciale ‘\’ perché altrimenti verrebbero trattate come caratteri normali/^[0-9]\{5\}$/
« corrisponde a qualunque riga che contenga esattamente 5 numeri e nient’altro./[^s]/
« corrisponde a qualunque riga che NON contiene la lettera ‘s’ minuscola[^[0-9]]
« corrisponde a qualunque riga che non contiene dei numeri[[:punct:]]
« corrisponde a qualunque riga contenga dei caratteri di punteggiatura[[:space:]0-9]
« corrisponde a qualunque riga contenga degli spazi bianco o dei numeri[[:space:][:digit:]]
« come il precedente
NOTA: se utilizziamo l’espressione regolare per la semplice ricerca quel che cerchiamo sono le “linee” o “righe” di testo che corrispondono alla regex. Quando le utilizziamo per la sostituzione esse corrisponderanno esattamente ai caratteri corrispondenti con la regex. Se per esempio ‘s/^ciao/Ciao/’ in una sostituzione indica di sostituire tutte le scritte “ciao” con “Ciao” ma solo se “ciao” è la prima parola della riga, cercando invece ‘/^ciao/’ il comando sed stamperà tutte le righe che cominciano con “ciao” e non solo la parola trovata 🙂
per far qualche prova…
scrivetevi un file di testo e salvatelo, quindi provate ad eseguire su di esso delle regex di ricerca con questo comando:
sed -n -e '/la vostra regex qui tra gli slash/p' nome-vostro-file.txt
il comando qui sopra stamperà SOLO le righe che sono riconosciute dalla vostra regex! Limitatevi a cambiare il contenuto tra i due slash e il nome del file per ora. Dopo vi spiegherò meglio come usare sed.
Se volete provare con delle sostituzioni usate questo comando
sed -e 's/regex/testo sostitutivo/g' nome-vostro-file.txt
questo comando lo avete già visto! provatelo, utilizzate eventualmente la e-commerciale (&)
Se ora riguardate l’espressione che ho usato dovreste capire che corrisponde a: due numeri, due punti, due numeri, due punti, due numeri. 🙂 [mi riferisco all’esempio di questo articolo]
Le linee accettate da quell’espressione sono tutte quelle in cui è contenuta tale sequenza. Nel carattere ‘&’ viene sostituita esattamente la sequenza riconosciuta.
Approfondimenti sulle regular expression
9 novembre, 2012 at 12:19
Ciao a tutti, mi è capitato di vedere una cosa del genere in un’espressione regolare:
jpe?g
Sapreste dirmi cosa significa?
Grazie 🙂
Roberto
13 novembre, 2012 at 19:20
Significa jpg o jpeg
il punto di domanda è dice “il precedente carattere può esserci o non esserci”
15 novembre, 2012 at 11:14
L’avevo immaginato, però volevo una conferma! Grazie 1000 🙂
23 settembre, 2011 at 11:56
Ciao a tutti io ho questa frase 50 Watt x 4 e la devo far diventare 50 x 4
come faccio?
grazie
13 novembre, 2012 at 19:34
Potresti provare a leggere l’articolo 🙂
se la cosa è didattica…
assumendo che quel che vuoi fare è estrarre i 2 numeri della stringa:
echo ‘Ciao a tutti io ho questa frase 50 Watt x 4’ | sed ‘s#[^0-9]*\([0-9]\+\)[^0-9]*\([0-9]\+\).*#\1 x \2#’
cioè: scarta tutto ciò che non è un numero, poi prendi un numero, poi scarta ciò che non è un numero e prendi un altro numero, scarta tutto il resto della stringa
scrivi il primo numero, spazio ‘x’ spazio secondo numero
ho usato i grouping.
20 agosto, 2011 at 1:21
ho un problema che mi assilla premetto che ho queste righe per ogni record passato
[topolino minnie paperino]
[paperino topolino]
[pluto topolino paperino minnie]
[minnie]
…
come si e capito le varie righe hanno all’interno dei valori che non compare sempre negli stessi posizionamenti e sopratutto possono essere dinamici, altro record :
[milan inter roma genoa sampdoria]
[juve]
[roma lazio verona inter]
ora :
devo cercare effettuare la ricerca per ogni singola riga, ordinare e togliere vari doppioni record
p.s. c’e’ “[” ad inizio e la “]” a fine riga
i risultati per i 2 esempi dovrebbero essere questi
record 1 :
1) minnie
2) paperino
3) pluto
4) topolino
record 2 :
1) genoa
2) inter
3) juve
4) lazio
5) milan
6) roma
7) sampdoria
8) verona
alla fine l’espressione regolare dovrebbe essere :
cerca dall’inizio a partire da “[” ogni parola divisa da uno spazio fino a quando non si incontra la fine “]”, ordinale alfabeticamente e togli i doppi
ho utilizzato questa (^\S+)
13 novembre, 2012 at 19:31
Ciao,
Non so con che linguaggio stai lavorando.
Ma non ti basta una espressione regolare per fare quel che vuoi.
il modo più semplice, se stai usando un sistema Linux / Unix e hai una shell a disposizione è usare sed.
Ho una guida qui sul blog su sed.
qualcosa come:
cat | sed ‘s#[]\[]##g;s#[[:space:]]\+#\n#g’ | sort | uniq
dandogli in pasto il primo record del tuo esempio si ottiene:
minnie
paperino
pluto
topolino
per spiegare le due regex:
s#[]\[]##g
significa: sostituisci qualunque ] o qualunque [ con niente (g = più volte)
è importante che la ] sia il primo carattere perché altrimenti verrà confuso come il carattere di chiusura, il [ invece va escapato con il back slash
questa invece:
s#[[:space:]]\+#\n#g
dice di sostituire le sequenze di almeno un carattere di spazio con un newline (\n)
sort = ordina le stringhe
uniq = rimuove i duplicati
scusa il ritardo nella risposta
20 luglio, 2011 at 10:59
Qualcuno ha idea di quale sia la differenza tra .* e .*?….???
Grazie dell’aiutoooo……
26 luglio, 2011 at 15:35
Ciao Luca
è una notazione che dice se consumare i caratteri in modo *ingordo* o *parsimonioso, pigro se preferisci*, in inglese greedy/eager e nongreedy/lazy
normalmente
.*
e.+
sono ingorde, se si aggiunge il punto di domanda diventano pigre:.*?
e.+?
che significa in sostanza?
ti faccio l’esempio classico:
<h1>Questo è un titolo HTML</h1>
Supponi di voler rimuovere i tag
<h1>
e</h1>
o in generale i tagla regular expression:
<.+>
sembrerebbe corretta, ma non lo è. perché rimuoverebbe tutto
immaginati di *mangiare* la stringa sopra partendo da sinistra…
trovi la prima
<
e la ingoi, prosegui e ingoi qualunque carattere perché la regex dice[^>]+
dove il + vuol dire 1 o piùla regex dice che alla fine deve esserci un
>
ma siccome non hai messo il punto di domanda sei ingordo e ti *mangi* tutta la stringa fino all’ultimo>
che trovi, ovvero fino al</h1>
finalese invece usi questa regex:
<.+?>
quando arrivi al primo
>
ti fermi, perché sei pigro / non sei ingordopiù avanti nella stringa troverai anche
</h1>
che matcha.e quindi non tocchi il contenuto: “Questo è un titolo HTML”
spero di essere stato chiaro 🙂
altrimenti cerca esempi cercando i termini inglesi
ciao
ps: ho modificato il commento perché wordpress si è mangiato i miei caratteri la prima volta, interpretandoli come HTML
pps: avevo scritto una cosa sbagliata inizialmente, la regex
<[^>]+>
sarebbe stata corretta comunque26 novembre, 2009 at 12:24
L’esercizio è Public Stati boolean checkString(String s), prende in input una stringa e mi dice se è ben formata: costituita da sequenze di 0 più caratteri diversi dalle parentesi racchiusi tra coppie di parentesi angolari.
Come si fa?
Grazie
26 novembre, 2009 at 23:51
cos’è un esercizio java?
(static non stati)
non so se dovrei risolverti gli esercizi java…
poi dubito tu li capisca…
dovresti sbatterci la testa tu
comunque ti aiuto…
se ti impegni e non riesci ti aiuterò di più…
primo: in java alcuni caratteri, come la barra ‘\’ sono “speciali” e quindi devi farne l’escape: \ = \\ in java.
perché ad esempio \n è un a capo \t un tab e così via…
allora.. un insieme di caratteri in una regex sta tra parentesi quadre:
[abcd]
vuol dire: qualunque carattere che sia ‘a’, ‘b’, ‘c’ o ‘d’
oppure puoi fare l’opposto
[^abcd]
vuol dire: qualunque carattere che NON sia ‘a’, ‘b’, ‘c’ o ‘d’
a te serve qualunque carattere non sia una parentesi.. una parentesi può essere (, ), [, ], {, }
le parentesi però sono caratteri particolari nelle regex quindi dovrai farne un escape…
in una regex un escape di [ è \[, in java sarà \\[ perché la barra deve essere doppia.
non so cosa si intenda per parentesi angolari… forse ?
questa regex:
dice: qualunque sequenza di zero o più caratteri che non contenga ‘a’, ‘b’, ‘c’ o ‘d’ e sia racchiusa da
dovrei averti aiutato… prova a sbatterci un po’ la testa e se vuoi fammi qualche domanda più mirata
16 settembre, 2009 at 17:41
Ciao a tutti mi potete dare una definizione formale di espressione regolare che sia in italiano e che non dica che è una sintassi e che non dica che è un tipo di espressione..
GRAZIEEE
16 settembre, 2009 at 23:40
Ciaro Riccardo,
non penso di comprendere bene cosa tu voglia…
una regex è una sintassi per descrivere stringhe.
e sintassi è una parola italiana
si può anche descrivere una regex in modo matematico..
ne trovi un esempio su wikipedia (ita)
http://it.wikipedia.org/wiki/Espressione_regolare
Un’altro modo per definire una regex è:
un insieme di caratteri che rispetta una forma di linguaggio ben definita e che può essere utilizzata per descrivere stringhe e sequenze di testo.
ma perché ti serve una definizione formale?
20 luglio, 2009 at 23:13
[…] compreso e fatto un po’ di pratica con le regular expression (o regex) di cui vi ho parlato qui. Non sono richieste particolari esperienze di programmazione ma aiutano […]
14 luglio, 2009 at 17:02
Ti amo *.* Mi stai salvando da un esame
14 luglio, 2009 at 22:43
azz
se eri una bella ragazza ero più contento 😛
cmq se impari le regex ti salverai da molto di più che un esame… 😀
4 giugno, 2009 at 22:53
grande!
odio le espressioni regolari ma i tuoi esempi vanno forte per molte esigenze!
4 giugno, 2009 at 23:08
e perché mai odiare la cosa più utile di questo mondo?
le regex ti vogliono bene
comprendile e tante, tante cose ti verranno più facili!
19 marzo, 2009 at 20:53
@gio
c’è qualcosa che non ti è chiaro nella guida?
cosa non ti riesce?
sei tu che sai cosa vuoi ottenere, non posso fartelo io questo lavoro
se mi dici qual’è il problema o dove non riesci posso anche aiutarti
19 marzo, 2009 at 16:32
ciao sapreste dirmi come tradurre in espressione regolare una stringa del tipo:
[31.22291:29.934612;31.20382:30.026973;31.09665:30.011724;31.11636:29.916851]
dove i decimali di ciascun numero possono variare in numero
grazie!
18 dicembre, 2008 at 21:36
@sartor
non ho capito cosa intendi per “un’altra utile”
18 dicembre, 2008 at 19:24
un ‘altra utile potrebbe essere:
-> ‘#.*file’ : visualizza tutte le righe contenenti il carattere “#” seguito da qualunque carattere e poi la parola “file”
3 dicembre, 2007 at 21:45
@mazzjoe
le regexp sono sempre quelle per tutti i programmi
talvolta varia leggermente la sintassi…
cioè ad esempio non serve metter / e / ad inizio e fine
però se le hai imparate con un qualunque tool/linguaggio poi son le stesso ovunque
3 dicembre, 2007 at 19:37
scusami ma io le regexp le conosco grazie a perl.. non mi sembra che cambiano molto.. non trovi?
ciao
3 dicembre, 2007 at 13:50
@Stemby
grazie ho corretto 🙂
era ovviamente sbagliato! 😛
piccola svista ma spero che l’abbiano notata anche gli altri, come te
3 dicembre, 2007 at 12:14
Scusa il doppio post, ma credo che lo stesso errore sia presente alla riga successiva.
3 dicembre, 2007 at 12:11
/}^/ « corrisponde a qualunque linea finisca con ‘}’
sto imparando ora i primi rudimenti grazie alla tua guida, quindi magari mi sbaglio, ma da quello che ho finora letto (sulla tua guida ;-)) credo che questa riga sia da correggere con
/}$/ « corrisponde a qualunque linea finisca con ‘}’
Comunque complimenti, molto chiaro ed interessante!
2 dicembre, 2007 at 21:24
@ercoppa
quello su awk sarà forse un po’ più complesso ma in assoluto il più interessante (almeno a mio parere)
lo sto preparando.. ci andrà ancora un po’
2 dicembre, 2007 at 21:04
Interessante questa serie di articoli, complimenti!
2 dicembre, 2007 at 20:12
[…] stava però diventando mastodontico! Quindi qui dentro vi linkero gli articoli che introducono regexp, sed e […]
2 dicembre, 2007 at 20:09
[…] delle espressioni regolari, se ancora non lo avete letto o non le conoscete leggetevi prima questo articolo. Un esempio semplice di utilizzo di sed lo trovate invece […]