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