Discover millions of ebooks, audiobooks, and so much more with a free trial

Only $11.99/month after trial. Cancel anytime.

RegEx3: L'uso delle espressioni regolari nelle applicazioni e nei linguaggi
RegEx3: L'uso delle espressioni regolari nelle applicazioni e nei linguaggi
RegEx3: L'uso delle espressioni regolari nelle applicazioni e nei linguaggi
Ebook967 pages13 hours

RegEx3: L'uso delle espressioni regolari nelle applicazioni e nei linguaggi

Rating: 1 out of 5 stars

1/5

()

Read preview

About this ebook

Con l'esperienza fatta con la prima e la seconda edizione si è deciso di integrare il testo con una serie di esercitazioni pratiche assistite, ricche di esempi applicativi.
Si è pensato – come si espone dettagliatamente nella parte che chiarisce le motivazioni dell'eBook – che quando tutto ciò che si vuole fare è ottenere la convalida dei propri file in HTML o semplicemente eseguire velocemente operazioni di sostituzione su un testo analizzato, se si ha bisogno di raggiungere velocemente uno scopo usando le espressioni regolari, ci si troverà divisi tra avere troppo poche informazioni per essere produttivi e avere troppe informazioni per sapere da dove cominciare.
Perciò si è deciso di integrare l'esposizione con una nutrita serie di esercitazioni guidate, che espongono con criterio incrementale le modalità di utilizzo dei vari operatori, chiarendo con esempi pratici e visivamente immediati le modalità di funzionamento delle regex.
Si spera che lo sforzo possa aver raggiunto lo scopo.
LanguageItaliano
PublisherMario Canton
Release dateJun 20, 2018
ISBN9788828338406
RegEx3: L'uso delle espressioni regolari nelle applicazioni e nei linguaggi

Read more from Mario Canton

Related to RegEx3

Titles in the series (3)

View More

Related ebooks

Programming For You

View More

Related articles

Reviews for RegEx3

Rating: 1 out of 5 stars
1/5

1 rating0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    RegEx3 - Mario Canton

    RegEx³

    L'uso delle espressioni regolari

    nelle applicazioni

    e nei linguaggi


    di Mario Canton

    2018 • 3ª Edizione digitale

    PROPRIETÀ INTELLETTUALE LETTERARIA RISERVATA

    © Copyright 2018 by Mario Canton

    3ª Edizione digitale – 2018

    ––=ooOoo=––

    Se si volesse condividere questo ebook con altre persone, si chiede cortesemente di scaricare una copia a pagamento per ciascuna delle persone a cui si vuole assegnarlo in uso.

    Se si sta leggendo questo ebook e non lo si è acquistato, qualora sia di gradimento, si chiede cortesemente di acquistarne una copia a pagamento per sostenere la continuità e il miglioramento dell'attività così da consentire l'opportunità di poter offrire ulteriori titoli con una qualità sempre crescente.

    Si ringrazia per il sostegno e il rispetto per il lavoro dell'autore, del redattore e dell'editore di questa pubblicazione.

    ––=ooOoo=––

    Note

    Se il lettore fosse gentilmente disponibile a collaborare per il miglioramento dell'opera, è possibile segnalare qualsiasi refuso e/o malfunzionamento operativo incontrato nella lettura dell'ebook inviando una e-mail all'indirizzo dell'autore (mario.canton@tiscali.it).

    L'autore si impegna ad apportare nel più breve tempo possibile le correzioni ritenute opportune e/o necessarie.

    Grazie sin d'ora per l'eventuale collaborazione.

    ––=ooOoo=––

    Avvertenze

    È stato fatto ogni sforzo per realizzare questo libro nella forma più completa e accurata possibile, ma non c'è alcuna garanzia implicita sulla perfetta accuratezza del contenuto.

    I linguaggi e gli strumenti di sviluppo vengono aggiornati molto rapidamente, perciò i contenuti di questo ebook sono fedeli allo «stato dell'arte» alla data di pubblicazione, come pure il livello di aggiornamento dei dati indicati.

    Le informazioni sono riportate «così come sono».

    Pertanto, l'autore non è responsabile di eventuali danni derivanti dall'applicazione delle informazioni contenute in questa pubblicazione.

    Sintesi, citazioni o estratti di parti di altre pubblicazioni e la loro evidenziazione sono effettuate ai sensi dell'art. 70 della legge 22 aprile 1941, n. 633, in quanto utilizzate per fini di ricerca o discussione, nei limiti giustificati da tale scopo, e non intendono mettersi in concorrenza con l'utilizzo economico delle opere riprodotte, citate o sintetizzate.

    ––=ooOoo=––

    Alla memoria

    del prof. Stephen Cole Kleene,

    (* 5.1.1909 † 25.1.1994)

    con somma gratitudine ...

    ... per tutta la fatica evitata,

    per tutta la precisione ottenuta

    e per tutto il tempo della mia vita

    risparmiato e dedicato ad altro.

    Indice

    Perché un eBook sulle RegEx?

    Utilità di questo eBook

    Prefazione alla 1ª edizione

    Prefazione alla 2ª edizione

    Prefazione alla 3ª edizione

    Ringraziamenti

    Due parole sulle origini

    Le implementazioni

    Gli automi finiti

    L'utilizzo delle espressioni regolari

    Terminologia

    Differenti «motori» delle RegEx

    Un prima prova con le RegEx

    Introduzione

    Le espressioni regolari

    Metacaratteri

    Rappresentativi

    Quantificatori

    Ancoraggi

    Altri

    Metacaratteri di tipo rappresentativo

    Punto «.»

    Lista «[...]»

    Intervallo nelle liste

    Padroneggiare i caratteri accentati (con POSIX)

    Lista negata «[^...]»

    Metacaratteri di tipo quantificatore

    Opzionale (punto interrogativo) «?»

    Come leggere una espressione regolare

    Asterisco «*»

    Introduzione del concetto di «golosità» (avidità, greediness)

    Introduzione del concetto di «jolly» (.*)

    Più «+»

    Graffe (parentesi) «{n,m}»

    Metacaratteri di tipo ancoraggio

    Circonflesso (accento) «^»

    Dollaro (segno del) «$»

    Bordo «\b»

    Altri metacaratteri

    Escape «\»

    O (alternativa) «|»

    Gruppo «(...)»

    Retrovisore (backreference) «\1 ... \9»

    Ulteriori dettagli

    Sui Metacaratteri

    Tempi e applicazioni diverse, distorsione di metacaratteri

    Quantificatori golosi

    Quantificatori non-golosi

    Metacaratteri tipo barra-lettera

    Metacaratteri moderni

    Precedenza tra metacaratteri

    Gli operatori fondamentali per la ricerca – Trattazione sistematica

    Un ricerca base

    Il punto

    Le cifre

    Gli spazi

    Gli insiemi di caratteri (set)

    Le sequenze di caratteri [ - ]

    Tutti i caratteri «tranne» [^ ]

    Le parole

    Ancore

    I caratteri di una parola \w

    Non-codici

    I confini di una riga

    I confini di tutto un testo

    I quantificatori Uno o più caratteri: +

    I quantificatori Zero o più caratteri: *

    I quantificatori Zero o uno: ? (eventualità)

    I quantificatori Il numero di ripetizioni: { }

    Quantificatori avidi o pigri (greedy o lazy)

    I raggruppamenti: Il riferimento all'indietro (backreference)

    I raggruppamenti: I gruppi di espressioni (…)

    I raggruppamenti: Il gruppo nominato (?P< > )

    I raggruppamenti: Il gruppo passivo (?: )

    I raggruppamenti: L'espressione condizionale (?: )

    I raggruppamenti: L'alternativa: |

    La codifica: Unicode

    La codifica: ASCII

    Guardarsi intorno (lookaround): Guarda avanti se diverso (?! )

    Guardarsi intorno (lookaround): Guarda avanti se uguale (?= )

    Guardarsi intorno (lookaround): Guarda indietro (?

    Caratteri particolari: bell \a (alarm)

    Caratteri particolari: Carattere di controllo \c

    Caratteri particolari: Carattere di escape \e

    Caratteri particolari: Carattere form feed \f

    Caratteri particolari: Caratteri a-capo e ritorno carrello \n e \r

    Caratteri particolari: Caratteri di tabulazione \v e \t

    Commento (?# )

    I modificatori: Maiuscole e minuscole uguali /i

    I modificatori: Modalità singola riga /s

    I modificatori: Modalità multi-riga /m

    Princìpi

    Non complicare

    Usare il circonflesso

    Evitare la lista negata

    Evitare la wildcard

    Essere specifici

    Niente follia ma razionalità

    Operazioni

    Problemi con maiuscole e minuscole

    Espressioni regolari pre-processate e «crude»

    Multilinearità

    Accentazione

    Errori e incovenienti

    Backtracking quantificatori possessivi e gruppi atomici

    Individuare un file HTML completo

    Ripetere un gruppo catturato e raggruppare un gruppo ripetuto

    Esempi

    Individuare tag in (X)HTML

    Eliminare gli spazi vuoti

    Indirizzi IP

    Individuare numeri in virgola mobile

    Trovare e validare un indirizzo e-mail

    Individuare una data valida

    Individuare una intera linea di testo

    Trovare linee che contengono (o non contengono) determinate parole

    Cancellare linee duplicate in un file

    Rimuovere parti duplicate in una stringa

    Individuare commenti

    Individuare stringhe

    Individuare numeri

    Individuare parole particolari o parole chiave

    Trovare due parole vicine l’una all’altra

    Espressioni regolari per e-book

    Trasformare gli spazi doppi in spazi singoli

    Cancellare tutti i tabulatori

    Cancellare le linee bianche (con codifica Windows)

    Eliminare gli spazi vuoti di inizio riga

    Eliminare gli spazi vuoti a fine riga

    Eliminare le interruzione di riga interne ai paragrafi

    Inserire tutte le linee tra i tag di paragrafo «

    »

    Aggiungere una «class» alle interruzioni di sezione

    Aggiungere un attributo «alt» a tutte le immagini

    Sostituire «&» con «&»

    Sostituire apostrofi normali con apostrofi orientati

    Modificare la marcatura dei titoli

    Cambiare il formato delle date

    Trovare caratteri speciali

    Trovare caratteri speciali (escludendo apici inclinati e lineette)

    Aggiungere lo stile «centrato» alle interruzioni di sezione stile Markdown

    Cancellare le linee bianche con esclusione dell’ultima

    Aggiungere ai capitoli lo stile «capitolo»

    Sostituire i tag segnaposto nei file XHTML provenienti da file di word processor

    Le sostituzioni

    Le espressioni regolari nelle applicazioni e nei linguaggi

    grep

    Java

    JavaScript

    Microsoft .NET

    Microsoft SQL Server T-SQL

    Microsoft Visual Studio .NET

    MySQL

    Oracle PL/SQL

    Perl

    PHP

    Python

    Gli editor di testo

    EditPad (Lite|Pro) con RegexBuddy e RegexMagic

    RegexBuddy

    RegexMagic

    Emacs

    Microsoft Word

    Notepad++

    (Libre|Apache|Open) Office Writer

    Vim

    Software applicativi

    Fogli di calcolo

    Google Docs – Fogli

    Data Base

    MySQL

    Le Espressioni Regolari di MySQL con l'Operatore REGEXP

    Oracle

    PostgreSQL

    SQLite

    App e shell

    Apache HTTPd

    Awk

    Find

    Grep

    Nginx

    PowerGrep

    PowerShell

    Sed

    Shell Script (Bash)

    Equivalenza tra glob ed espressioni regolari

    Linguaggi di programmazione

    C

    C++

    Delphi

    HTML5

    Java (con Groovy)

    Groovy

    JavaScript / ActionScript con XregExp

    .NET

    Perl

    PHP

    Il set di funzioni «preg»

    Il set di funzioni «ereg»

    Il set di funzioni «mb_ereg»

    PCRE

    POSIX

    Python

    Flags

    Gruppi nominati

    R

    Ruby

    Tcl

    VBscript (Visual Basic)

    XML

    Classi di caratteri in XML

    XQuery e XPath

    Tre funzioni Regex

    Xojo (Real Basic)

    Librerie e programmi correlati

    Librerie

    wxWidgets

    La classe wxRegEx

    Funzioni di stato wxRegEx

    Trovare ed estrarre occorrenze

    Ricerca e Sostituzione

    POSIX Base (BRE – Basic Regular Expressions)

    POSIX Esteso (ERE – Extended Regular Expressions)

    L'alternanza POSIX ERE restituisce l'occorrenza più lunga

    Estensioni GNU delle Espressioni Regolari

    GNU Basic Regular Expressions (grep, ed, sed)

    GNU ERE (Extended Regular Expressions) – (egrep, awk, emacs)

    Estensioni GNU addizionali

    Gnulib

    PCRE

    Usare PCRE

    Compilare PCRE con Supporto Unicode

    PCRE Callout

    UTF-8, UTF-16 e UTF-32

    PCRE2

    UTF-8, UTF-16 o UTF-32

    Usare PCRE2

    Sostituire le occorrenze

    Programmi

    Tabelle riassuntive

    Differenze di metacarattere tra le applicazioni

    Sintesi dei metacaratteri e dei loro dettagli

    POSIX, barra-lettere e altra simbologia

    Metacaratteri moderni, patch e precedenze

    Caratteri ASCII stampabili (ISO-8859-1)

    Prospetti riassuntivi di riferimento

    Metacaratteri definiti con esempi

    Escape di caratteri

    Classi di caratteri

    Modificatori

    Lista di alcuni editor con le varianti di regex supportate

    Tester per espressioni regolari

    Esercitazione 1

    Nozioni base

    Capire qual è la necessità

    Come vengono usate le espressioni regolari

    Ricerche RegEx

    Sostituzioni RegEx

    Perciò, cos'è esattamente un'espressione regolare?

    Usare le espressioni regolari

    Prima di iniziare le esercitazioni

    Sintesi

    Esercitazione 2

    Individuare singoli caratteri

    Individuare testo letterale

    Quante occorrenze?

    Gestire le differenze maiuscolo / minuscolo

    Individuare qualsiasi carattere

    Individuare caratteri speciali

    Sintesi

    Esercitazione 3

    Individuare set di caratteri

    Individuare uno tra diversi caratteri

    Utilizzo dei set di caratteri

    Individuazione di «Qualsiasi cosa tranne»

    Sintesi

    Esercitazione 4

    Uso dei metacaratteri

    Escape rivisitato

    Individuare caratteri a spazio bianco

    Individuare tipi specifici di carattere

    Individuare cifre (e non-cifre)

    Individuare caratteri alfanumerici (e caratteri non-alfanumnerici)

    Individuare spazi bianchi (e non-spazi bianchi)

    Specificare valori esadecimali o ottali

    Usare valori esadecimali

    Usare valori ottali

    Usare classi di carattere POSIX

    Sintesi

    Esercitazione 5

    Abbinamenti ripetuti

    Quante occorrenze?

    Individuare uno o più caratteri

    Individuare zero o più caratteri

    Indiduare zero o un carattere

    Usare gli intervalli

    Individuare un intervallo esatto

    Individuare un intervallo di gamma

    Individuare un intervallo di «Almeno»

    Prevenire l'individuazione

    Sintesi

    Esercitazione 6

    Individuazione della posizione

    Usare i confinamenti

    Usare i confini di parola

    Definire i confini delle stringhe

    Usare la modalità multilinea

    Sintesi

    Esercitazione 7

    Utilizzo di sottoespressioni

    Comprendere le sottoespressioni

    Raggruppamenti con le sottoespressioni

    Sottoespressioni annidate

    Sintesi

    Esercitazione 8

    Usare le backreference

    Comprendere le backreference

    Individuazione con le backreference

    Compiere operazioni di sostituzione

    Conversione maiuscole-minuscole

    Sintesi

    Esercitazione 9

    Looking ahead e behind (guardare avanti e indietro)

    Introduzione al Lookaround (guardarsi intorno)

    Looking ahead (guardare avanti)

    Looking behind (guardare indietro)

    Combinare l'osservazione avanti e indietro

    Lookaround negato

    Sintesi

    Esercitazione 10

    Condizioni di incorporamento

    Perché usare condizioni incorporate?

    Usare le condizioni

    Condizioni di backreference

    Condizioni di Lookaround

    Sintesi

    Esercitazione 11

    Soluzione di problemi comuni con le espressioni regolari

    Numeri telefonici del Nord America

    Codici di avviamento postale (ZIP) degli Stati Uniti

    Codici postali canadesi

    Codici postali della Gran Bretagna

    Numeri di previdenza sociale degli Stati Uniti

    Indirizzi IP

    URL (indirizzo univoco di una risorsa in Internet)

    URL completi

    Indirizzi e-mail

    Commenti in HTML

    Commenti in JavaScript

    Numeri di Carte di Credito

    Sintesi

    Appendice tecnica

    Linguaggi, grammatiche e automi

    Linguaggi

    Grammatiche

    Linguaggi regolari ed espressioni

    Espressioni regolari

    Grammatiche regolari

    Automi a stati finiti

    Versione Deterministica

    Esempi

    Versione Non-deterministica

    Linguaggi liberi dal contesto

    (context-free languages)

    Grammatiche libere dal contesto

    (context-free grammars)

    Automi a pila

    (pushdown automata)

    Esempi

    Versione non-deterministica

    Esempi

    Dimostrazioni

    Teorema 1:

    Ogni linguaggio regolare è accettabile per qualche NFSA.

    Teorema 2:

    Ogni linguaggio regolare è anche libero dal contesto.

    Bibliografia essenziale

    Manuali generali

    Manuali su Perl con parti specifiche sulle ER

    Manuali specifici

    Manuali online

    Manuali su automi finiti, algebre,

    linguaggi ed espressioni regolari

    (.*?)

    Perché un eBook sulle RegEx?

    Le espressioni regolari e il linguaggio delle espressioni regolari esistono da molti anni. Gli esperti di espressioni regolari sono stati a lungo dotati di uno strumento incredibilmente potente, che può essere utilizzato per eseguire ogni sorta di eclettica elaborazione e manipolazione del testo in quasi tutte le lingue e su ogni piattaforma.

    Questa è la buona notizia. La cattiva notizia è che per troppo tempo, le espressioni regolari sono state di esclusiva proprietà solo dei più esperti di tecnologia. Molti di noi non comprendono appieno cosa fanno le espressioni regolari e quali problemi risolvono. E quelli che hanno provato a utilizzarle trovano che la sintassi delle espressioni regolari non sia per niente intuitiva e a volte persino contorta. È triste, perché la verità è che le espressioni regolari non sono affatto così complesse come sembrano a prima vista. Tutto ciò che serve è una chiara comprensione del problema da risolvere e come sfruttare le espressioni regolari in modo da risolverlo.

    Parte del problema è la scarsità di contenuti di qualità sull'argomento. I pochi libri sulle espressioni regolari e, in effetti, la maggior parte dei siti Web che vantano esercitazioni di espressione regolari, tendono a concentrarsi sulla sintassi, definendo cosa fa { e come + differisce da *. Ma questa è la parte facile; non ci sono molti caratteri speciali nel linguaggio delle espressioni regolari. La parte difficile è capire come dovrebbero essere utilizzati questi caratteri in modo da risolvere i problemi del mondo reale.

    Questo eBook non intende essere l'ultima parola su tutto ciò che c'è da sapere sulle espressioni regolari. Se questo è ciò che si desidera, bisogna acquistare una copia di Mastering Regular Expressions di Jeffrey Friedl (O'Reilly). Friedl è il più famoso guru delle espressioni regolari e il suo libro è il più completo ed esauriente sull'argomento. Ma, senza offesa per Friedl, il suo libro non è proprio per principianti o anche solo per utenti occasionali che vogliono solo svolgere il proprio lavoro senza aver bisogno di capire il funzionamento interno dei motori per espressioni regolari. Non che non siano informazioni utili – lo sono – ma non quando tutto ciò che si vuole fare è ottenere la convalida dei propri file in HTML o semplicemente eseguire velocemente operazioni di sostituzione su un testo analizzato. Se hai bisogno di raggiungere velocemente uno scopo usando le espressioni regolari, ti troverai diviso tra avere troppo poche informazioni per essere produttivo e avere troppe informazioni per sapere da dove cominciare.

    Ed è qui che si inserisce questo eBook per imparare le espressioni regolari per quello che si ha davvero bisogno di sapere, iniziando con semplici corrispondenze testuali e lavorando poi su argomenti più complessi, incluso l'uso di backreference, la valutazione condizionale e il procedimento lookaround. Si imparerà metodicamente, sistematicamente e semplicemente cosa è possibile utilizzare mediante esempi chiari e pratici e risolvendo problemi reali.

    Utilità di questo eBook?

    Questo eBook può servire se:

    Non si conoscono le espressioni regolari.

    Si vuole imparare rapidamente come ottenere il massimo dal linguaggio delle espressioni regolari.

    Si vuole ottenere un vantaggio imparando a risolvere problemi reali usando uno degli strumenti più potenti (e meno compresi) a propria disposizione.

    Si costruiscono applicazioni Web e si desidera una forma e un'elaborazione del testo più sofisticate.

    Si utilizzano JavaScript, Java, .NET, PHP, Python, MySQL (e qualsiasi altro linguaggio e DBMS con supporto per espressioni regolari) e si desidera imparare come utilizzare le espressioni regolari durante lo sviluppo della propria applicazione.

    Si vuole essere produttivi rapidamente e facilmente nell'uso delle espressioni regolari, senza dover chiamare qualcuno per chiedere aiuto.

    Quindi iniziamo mettendoci al lavoro. Sarà possibile sfruttare il potere delle espressioni regolari in pochissimo tempo e ci si chiederà poi come si sia mai potuto lavorare senza di loro.

    (.*?)

    Prefazione alla prima edizione

    Non ricordo più quando è stato il momento preciso in cui ho scoperto le espressioni regolari, ma posso dire che da allora trattare testi è diventato molto meno faticoso.

    L'utilizzo delle espressioni regolari non è molto diffuso tra autori, scrittori e redattori mentre programmatori, sviluppatori di codice e realizzatori di e-book ne fanno un frequente – e soddisfacente – impiego.

    Questa succinta guida all'uso delle «regex» o «regexp» (acronimi di origine inglese da «regular expressions») o – più semplicemente – «RE», è stato pensato proprio per chi si occupa di scrivere o revisionare testi.

    Delle regex esistono molte varianti (chiamate «flavours», letteralmente «sapori, gusti o aromi») ma sostanzialmente la logica è sempre la stessa e la sintassi non presenta moltissime differenze.

    Qui sarà trattata in prima battuta la sintassi relativa alla libreria PCRE (Perl Compatible Regular Expressions) cioè a quelle istruzioni che sono accettate dai software che utilizzano un funzionamento delle regex compatibile con quello del linguaggio Perl, da cui peraltro le regex sono state derivate per un impiego operativo.

    PCRE è una libreria sviluppata in linguaggio «C» ed è perciò estremamente efficiente e veloce.

    Molti editor e word processor ormai incorporano la «modalità regex» per effettuare ricerche, estrazioni e sostituzioni di testo.

    Un editor particolarmente utilizzato è Notepad++ ma anche il famosissimo Word di Microsoft, oppure l'open source LibreOffice (e il precedente OpenOffice) o ancora editor per lo sviluppo di software come UltraEdit o Dreamweaver e infine lo stesso Sigil, noto ai redattori di e-book in formato ePub, tutti incorporano una modalità «espressioni regolari».

    Sulle espressioni regolari esiste molto poco nella letteratura in lingua italiana; ben altra mole di documentazione è invece a disposizione se si conosce un po' la lingua inglese.

    Chi vorrà approfondire potrà trovare nella bibliografia alla fine di questo testo ottimi suggerimenti per le opere a stampa, di cui – il più delle volte – i loro autori forniscono anche una versione digitale, se si preferisce questa modalità di lettura.

    Cosa si può fare con le regex?

    Per rispondere, basta considerare che la ricerca di «stringhe» (sequenze di caratteri) da parte di un computer è molto veloce ma estremamente rigida.

    Con le espressioni regolari diventa invece possibile:

    – trovare se esistono nel testo determinate sequenze;

    – localizzare stringhe di caratteri che combaciano con le sequenze e sostituirle con qualcosa di diverso;

    – estrarre le stringhe che combaciano con le sequenze per poterle riutilizzare diversamente.

    Per non annoiare troppo il lettore l'esposizione sarà legata per quanto possibile ad esempi pratici, con i quali saranno illustrate, di volta in volta, le varie funzionalità delle regex.

    Ovviamente gli esempi saranno quelli che normalmente si trovano di fronte autori, scrittori e redattori.

    Buona lettura!

    Piove di Sacco, Dicembre 2016

    Mario Canton

    mario.canton@tiscali.it

    Prefazione

    alla seconda edizione

    Con l'esperienza fatta con la prima edizione si è deciso di integrare il testo con una guida più esemplificativa, in modo da poter accostare le espressioni regolari con un taglio più didattico.

    Si spera di aver ottenuto una maggiore semplicità di esposizione che renda meno ostico l'avvicinamento alle regex.

    In questa seconda edizione si sono anche prese in esame le varianti (flavours) più diffuse di motori per espressioni regolari, come quelle di editor (EditPad Pro e Lite, Emacs, MS Word, Notepad++, Libre/Apache/Open Office Writer, Vim), fogli di calcolo (Google Documenti – Fogli), database (MySQL, Oracle, PostgreSQL, SQLite), app e shell (Apache HTTPd, Awk, Find, Grep, Nginx, PowerGrep, PowerShell, Sed, ShellScript o Bash), linguaggi di programmazion (C, C++, Delphi, HTML5, Java (con Groovy), JavaScript/ActionScript (con XRegExp), .NET, Perl, PHP, Python, R, Ruby, Tcl, VBScript (Visual Basic), XML, XQuery e XPath, Xojo o Real Basic), librerie (vxRegex, POSIX Base, GNU, Reggex, PCRE) e tester (text2regex, VisualRegExp, Regex Coach, RegexPal, Regex101).

    Si presume che, anche se l'applicazione che si utilizza non è esplicitamente menzionata, probabilmente usi una variante che viene trattata sotto un'altra denominazione. In genere la maggior parte delle applicazioni sviluppate usano una delle varianti che sono state prese in esame, in quanto la maggior parte delle applicazioni vengono sviluppate utilizzando un ambiente di programmazione o delle librerie di espressioni regolari tra quelle considerate in questo ebook.

    Si è infine integrato la parte riepilogativa con ulteriori tabulati e quadri sinottici dei comandi e degli operatori (anche relativi alle diverse varianti) e aggiunto una breve appendice tecnica sugli automi finiti, l'algebra e i linguaggi regolari, che stanno alla base della «logica» delle regex.

    È stata riorganizzata la bibliografia per argomenti (trattazioni generali, Perl e regex, applicazioni specifiche, guide online e testi sulle correlazioni con gli automi a stati finiti).

    Buona lettura!

    Piove di Sacco, Gennaio 2018

    Mario Canton

    mario.canton@tiscali.it

    Prefazione

    alla terza edizione

    Con l'esperienza fatta con la prima e la seconda edizione si è deciso di integrare il testo con una serie di esercitazioni pratiche assistite, ricche di esempi applicativi.

    Si è pensato – come si espone dettagliatamente nella parte che chiarisce le motivazioni dell'eBook – che quando tutto ciò che si vuole fare è ottenere la convalida dei propri file in HTML o semplicemente eseguire velocemente operazioni di sostituzione su un testo analizzato, se si ha bisogno di raggiungere velocemente uno scopo usando le espressioni regolari, ci si troverà divisi tra avere troppo poche informazioni per essere produttivi e avere troppe informazioni per sapere da dove cominciare.

    Perciò si è deciso di integrare l'esposizione con una nutrita serie di esercitazioni guidate, che espongono con criterio incrementale le modalità di utilizzo dei vari operatori, chiarendo con esempi pratici e visivamente immediati le modalità di funzionamento delle regex.

    Si spera che lo sforzo possa aver raggiunto lo scopo.

    Buona lettura!

    Piove di Sacco, Giugno 2018

    Mario Canton

    mario.canton@tiscali.it

    Ringraziamenti

    Vorrei ringraziare tutti gli iscritti al gruppo Idac in Facebook, per la partecipazione ai sondaggi sulla scelta delle copertine delle varie edizioni di questo eBook. In particolare:

    ––=ooOoo=––

    Avvertenza generale


    Per evitare sconfinamenti dai margini dei dispositivi di lettura da parte di righe di codice molto lunghe, e al fine di migliorare l'esposizione e la lettura del testo, viene talora utilizzato in determinati punti delle stringhe il simbolo «➥», che sostituisce con un ritorno a capo forzato quello che nella riga di codice è un semplice spazio bianco (nelle stringhe di testo) o rappresenta invece una continuità dell'espressione (nelle regex).

    (.*?)

    Due parole sulle origini

    Chiunque abbia utilizzato un word processor conosce l'esistenza di funzioni che cercano e sostituiscono caratteri all'interno di un testo, sia automaticamente che su conferma da parte dell'utente.

    Possiamo vedere le «espressioni regolari» come una evoluzione di questi sistemi.

    Dal punto di vista storico – in realtà – le RegExp vengono molto prima dei sistemi di ricerca che si trovano nei word processor, anzi, questi ultimi sono basati proprio sulle prime, a volte su loro forme semplificate.

    Le espressioni regolari si possono far risalire alle prime ricerche sul sistema nervoso umano, quando i neurofisiologi Warren McCulloch e Walter Pitts svilupparono nel 1943 un sistema matematico per la descrizione delle reti neurali.

    Le «espressioni regolari» sono state sistematizzate nei successivi anni '40 da Stephen Cole Kleene, matematico statunitense, che con il suo omonimo famoso teorema afferma che sono equivalenti:

    (1) la classe di linguaggi di terzo tipo (secondo Chomsky o a grammatica formale),

    (2) quella dei linguaggi a stati finiti (automi a stati finiti, deterministici e non deterministici) e

    (3) quella dei linguaggi regolari (espressioni regolari).

    La seguente tabella sintetizza ciascuno dei quattro tipi di grammatica di Chomsky, la classe di linguaggio generata, il tipo di automa riconosciuto e le forme che devono avere le loro regole.

    Sulla base di quegli studi Kleen pubblicò una ricerca che introduceva il concetto di espressione regolare che fu utilizzata per descrivere l'algebra dei «regular sets» (insiemi regolari) detta, appunto, «algebra regolare».

    Le «espressioni regolari» sono state utilizzate operativamente solo dal 1966 quando furono inserite da Ken Thompson – uno dei padri del sistema operativo Unix – nell'editor chiamato QED – la prima applicazione pratica per le espressioni regolari – che veniva utilizzato come strumento di editing nelle prime versioni del sistema operativo.

    Dopo gli anni '80, le «espressioni regolari» si sono diffuse ampiamente con lo sviluppo del linguaggio di programmazione Perl, creato nel 1987 da Larry Wall.

    Oggi praticamente tutti i linguaggi di programmazione e moltissimi tra gli editor più avanzati – utilizzati in genere per scrivere codice – contengono un set di istruzioni relativo alle RegExp.

    (.*?)

    Le implementazioni

    Uno dei problemi che riguardano i motori delle espressioni regolari è la loro implementazione (la realizzazione concreta delle procedure a partire dalla loro definizione logica), su cui esistono due principali orientamenti.

    Per la comprensione dell'argomento è prima necessario definire cosa sia un «automa a stati finiti». Si tratta di un modello che descrive un comportamento in cui esiste un numero finito di stati e varie azioni che provocano la transizione da uno stato a un altro.

    Nella Fig. 1 viene descritto l'automa a stati finiti che descrive il semplice processo di accensione e spegnimento di una lampadina (l'automa in questo caso è rappresentato dall'interruttore di energia elettrica). Questo sistema estremamente semplice ha solo due stati e due azioni che determinano due transizioni.

    Lo stato iniziale è quello di «lampadina spenta». In questo stato esiste una sola possibile azione la pressione dell'interruttore che permette la transizione allo stato di «lampadina accesa». Nel nuovo stato è accessibile l'altra azione, la pressione dell'interruttore di energia elettrica che produce la transizione allo stato di «lampadina spenta».

    Fig. 1 – L'automa a stati finiti che descrive l'accensione di una lampadina.

    Una espressione regolare può essere rappresentata da un automa a stati finiti. Gli automi sono facilmente riproducibili da un computer, quindi è possibile usarli per creare un motore che li gestisca.

    Il metacarattere quantificatore «*», come vedremo nel dettaglio più avanti, significa «zero o più». Applichiamo questo concetto cercando di tradurre con un automa l'espressione regolare «ab*c».

    Nella Fig. 2 vediamo l'automa che rappresenta questa semplice espressione regolare.

    Dallo stato iniziale possiamo, se incontriamo la lettera «a», passare al secondo stato. A questo punto abbiamo due alternative: possiamo incontrare la lettera «c» che ci porta allo stato finale oppure possiamo incontrare la lettera «b» che ci porta di nuovo al secondo stato.

    Nota: Lo stato finale è rappresentato da un cerchio doppio.

    Fig. 2 – L'automa a stati finiti dell'espressione regolare «ab*c».

    Se l'automa analizza la stringa «xyabbcz» alla ricerca di una corrispondenza con l'espressione regolare «ab*c»,procedendo dalla prima lettera a sinistra e proseguendo verso destra, si verificano le seguenti fasi:

    lettera «x», siamo nello stato iniziale e non possiamo fare altro, nessuna corrispondenza e passiamo alla lettera successiva;

    lettera «y», siamo ancora nello stato iniziale e non possiamo fare altro, nessuna corrispondenza e passiamo alla lettera successiva;

    lettera «a», siamo sempre nello stato iniziale e possiamo andare allo stato successivo, che però non è un possibile stato finale;

    lettera «b», siamo nel secondo stato e possiamo effettuare una transizione verso lo stesso stato;

    lettera «b», siamo ancora nel secondo stato e possiamo effettuare una transizione verso lo stesso stato;

    lettera «c», siamo nel secondo stato e possiamo effettuare una transizione verso il terzo stato che è uno stato finale e ci permette di stabilire che è stata trovata una corrispondenza.

    Con questi passaggi si è potuto stabilire che l'espressione regolare «ab*c» ha una corrispondenza nella stringa «xyabbcz» a partire dalla terza lettera, la «a».

    Esistono due tipi di automi a stati finiti:

    gli automi a stati finiti deterministici (chiamati DFA dall'inglese «Deterministic Finite Automata»

    gli automi a stati finiti non deterministici (chiamati NFA dall'inglese «Non-deterministic Finite Automata»

    Nei DFA, in ogni stato la transizione è determinata, in modo univoco e senza possibili ambiguità, dalla prossima lettera incontrata, come gli esempi citati.

    Negli NFA in un dato stato possono esistere delle transizioni ambigue: una stessa lettera può portare a diversi stati successivi. Perciò il motore che interpreta l'automa, prima di poter stabilire se una espressione regolare individua o meno delle corrispondenze in una stringa, deve tornare sui propri passi e provare tutte le combinazioni possibili.

    A esemplificazione dei concetti espressi vediamo (Figg. 3 e 4) come l'espressione regolare «(c|d)*cdd», leggermente più complessa di quella già utilizzata sopra, viene rappresentata da un NFA e da un DFA .

    L'automa NFA è semplice, corrisponde in maniera diretta all'espressione regolare e in almeno un caso ha una transizione ambigua; dallo stato iniziale, se incontriamo la lettera «c» abbiamo due possibili transizioni: verso il secondo stato o indietro verso lo stato iniziale. L'espressione regolare rispecchia questa situazione; quando infatti incontriamo una lettera «c», non si può sapere se si è in presenza di una «c» che può essere ripetuta a piacere nella prima parte dell'espressione regolare «(c|d)*» o se siamo in presenza della «c» della seconda parte «cdd».

    L'automa DFA è più complesso e anche più difficile da costruire, perché ha più transizioni, ma offre il vantaggio di non mettersi mai davanti a un bivio: quando si incontra all'inizio una lettera «c» si passa sempre e comunque al secondo stato e così via.

    Fig.3 – L'automa a stati finiti di tipo NFA dell'espressione regolare «(c¦d)*cdd».

    Fig. 4 – L'automa a stati finiti di tipo DFA dell'espressione regolare «(c|d)*cdd».

    Nota: Se si prova a percorrere l'automa NFA e l'automa DFA con una stringa che corrisponda all'espressione regolare «(c|d)*cdd», per esempio «cccdcdd», si può notare che nel caso del secondo automa il percorso è sempre diretto e mai ambiguo. Nel caso del primo automa, invece, è necessario tornare indietro se si è scelto una strada sbagliata (per esempio se all'ultima «c» si è nello stato iniziale e non viene scelta la transizione che porta al secondo stato).

    Esistono quindi due possibili tipi di automi che possono rappresentare una stessa espressione regolare. Nel caso degli NFA si ha una rappresentazione più semplice ma un percorso più difficile. Nel caso dei DFA si ha una rappresentazione più complessa ma un percorso più semplice e diretto.

    Attualmente i due orientamenti operativi in essere seguono entrambi il metodo degli NFA, perché il problema della costruzione di un DFA a partire da un'espressione regolare può essere molto complesso e, a volte, richiedere un tempo estremamente alto. Viceversa, costruire un NFA a partire da un'espressione regolare è molto semplice e la complessità si sposta nella ricerca di un percorso verso l'individuazione di una corrispondenza.

    La differenza tra i due orientamenti attuali sta nella strategia adottata per affrontare la possibile ambiguità nella scelta delle transizioni tra i diversi stati.

    Un orientamento (di «backreference»), quando si trova in un vicolo cieco torna sui propri passi riprovando tutte le possibilità fino a esaurirle o fino a trovare uno stato finale.

    L'altro orientamento (a «multistati»), quando si trova di fronte a un bivio percorre entrambe le strade e memorizza contemporaneamente tutti i percorsi multipli.

    Nota: Questo ultimo orientamento segue l'algoritmo progettato per la prima volta da Ken Thompson nel 1968.

    In termini di performance l'orientamento della backreference si comporta estremamente meglio nella grande maggioranza dei casi. L'orientamento dei multistati invece è normalmente più lento ma, con alcune espressioni regolari molto complesse (rare o del tutto inusuali), surclassa clamorosamente l'avversario.

    Ad esempio, se dovessimo cercare in una stringa composta da ventinove lettere «l» consecutive:

    lllllllllllllllllllllllllllll

    una corrispondenza per la seguente espressione regolare:

    l?l?l?l?l?l?l?l?l?l?l?l?l?l?l?

    ➥l?l?l?l?l?l?l?l?l?l?l?l?l?l?

    il primo orientamento operativo impegnerebbe circa un minuto di CPU mentre il secondo ne impiegherebbe solo venti milionesimi di secondo. Una espressione regolare come questa non è per niente usuale, ma rimane comunque formalmente corretta.

    Il problema di stabilire quale orientamento sia il migliore può essere descritto in questo modo: dobbiamo andare al lavoro; possiamo usare un‘automobile velocissima ma che potrebbe, in casi rarissimi, procedere a 2 km/h per tutto il tragitto; in alternativa possiamo usare un‘automobile più lenta ma che non ci darà mai sorprese negative.

    Poiché non esiste una scelta sempre «giusta» a questa domanda, attualmente entrambi gli orientamenti hanno dei sostenitori.

    Comunque, la maggior parte delle implementazioni attuali ha seguito la scuola della backreference e solo in pochi casi esistono implementazioni della scuola a multistati. Questo perché l'implementazione di un motore con la «backreference» permette di avere espressioni regolari che hanno caratteristiche avanzate, come i gruppi e le alternative (vedi oltre per i due concetti). Queste stesse caratteristiche non possono essere ottenute con un motore a multistati.

    Nota: Un articolo che affronta in dettaglio la questione dei due orientamenti (scritto da Russ Cox) può essere letto (in inglese) qui: Implementazioni.

    Gli automi finiti

    Perché gli automi sono importanti? Una ragione è che quando hai bisogno di un'espressione regolare, a volte è più facile creare l'automa e poi derivare l'espressione regolare da quello. Quindi essere in grado di creare un automa per quello che si desidera può essere una buona abilità da possedere. In secondo luogo, alcuni programmi che accettano espressioni regolari come input, come grep e flex, convertiranno quell'espressione regolare in un automa per poi usarlo con un algoritmo molto veloce per eseguire la ricerca. Quindi è bene sapere in che modo le espressioni regolari e gli automi sono correlati. In terzo luogo, gli automi sono un modello computazionale elementare e sono molto importanti nella teoria del calcolo.

    Un automa è un piccolo computer molto semplice. Ha un insieme di stati e transita da uno stato all'altro secondo la sequenza di ingressi che legge. Gli input sono solitamente rappresentati come una stringa di simboli o caratteri. Uno degli stati è lo stato di partenza e uno o più stati sono stati finali. Lo stato iniziale può anche essere uno stato finale. Il calcolo che esegue è una risposta sì o no alla domanda: la sequenza di input sposta l'automa dallo stato iniziale a uno degli stati finali? La risposta dipenderà ovviamente da come sono collegati gli stati. Esaminare come tutto questo funziona richiede alcune notazioni e definizioni formali.

    Poniamo che «Q» rappresenti l'insieme di stati di un automa e poniamo che qi∈Q sia un elemento di «Q». Sia q0∈Q lo stato di partenza. L'automa inizia sempre in questo stato. Sia E⊆Q l'insieme degli stati finali. Se l'automa si trova in uno stato qi∈E alla fine dell'input, si dice che l'input è accettato. Gli stati finali sono talvolta chiamati stati di accettazione o stati finali. Poniamo che ∑ sia un insieme finito di simboli o caratteri chiamati alfabeto. La sequenza di input consisterà in una stringa di caratteri presi da ∑. Sia δ(qi,a)=qj la funzione di transizione dell'automa. La funzione dice che se l'automa è nello stato qi e il prossimo simbolo di input è a∈∑ allora l'automa si sposterà nello stato qj. Se l'automa è nello stato qi e legge un simbolo per il quale non è definita alcuna transizione, si ferma e l'input non viene accettato.

    Come abbiamo già accennato, se un automa presenta delle transizioni o se ha uno stato con due transizioni diverse per lo stesso simbolo di input, allora è chiamato non deterministico. Altrimenti si chiama deterministico. Le sigle NFA e DFA sono usate per automi finiti non deterministici e deterministici. Ogni NFA può essere trasformato in un DFA equivalente con un numero maggiore di stati.

    Un modo per caratterizzare la famiglia di stringhe accettate da un automa è un'espressione regolare (si veda la discussione nell'apposita sezione). In alcuni casi, per un piccolo automa, è possibile annotare l'espressione regolare mediante ispezione, ma in generale l'automa dovrà essere semplificato rimuovendo alcuni dei suoi stati per creare un automa equivalente più piccolo..

    Si tenga presente che mentre la lingua accettata da un automa finito può essere descritta da un'espressione regolare, l'espressione regolare non deve necessariamente essere unica. È possibile avere due diverse espressioni regolari che descrivono la stessa lingua. Quando si eliminano stati in un automa, l'ordine in cui vengono eliminati a volte può portare a espressioni regolari diverse che sono ugualmente valide. Questo è analogo al fatto che è possibile avere due polinomi equivalenti, uno dei quali è una forma semplificata di un altro in cui i termini ridondanti sono stati annullati.

    (.*?)

    L'utilizzo

    delle espressioni regolari

    Questa guida operativa è finalizzate a mettere in grado chiunque di utilizzare le espressioni regolari che consentono di risparmiare moltissimo tempo nel trattamento di testi. Si inizia dai concetti più basilari, in modo che le istruzioni possano essere eseguite anche da chi non conosce ancora nulla riguardo alle espressioni regolari.

    Le istruzioni tentano anche di far capire come funziona il «motore interno» delle espressioni regolari mettendo in guardia l'utilizzatore sulle eventuali conseguenze. Questo approccio aiuta a comprendere velocemente perché una particolare regex non faccia quello che inizialmente ci si aspettava. Questo risparmierà un mucchio di congetture e perplessità quando sarà necessario scrivere delle regex più complesse.

    Terminologia

    Fondamentalmente, una espressione regolare è un modello schematico che descrive una certa quantità di testo. Il nome deriva dalla teoria matematica su cui si basa. Ma non approfondiremo questa questione di cui qualcosa si è già detto nelle premesse. Come si è detto, appunto, il termine «espressione regolare» viene spesso abbreviato in regex (RegEx) o regexp (RegExp). Questa guida userà spesso l'abbreviazione «regex», perché più facile da pronunciare rispetto a «regexp». In questa guida le espressioni regolari sono scritte con una formattazione diversa da quella utilizzata per il testo normale, come ad esempio per «regex». Gli spazi, per essere visualizzati, sono spesso sostituiti dai punti di sospensione (tre consecutivi: ...) .

    Questo primo esempio è in realtà una regex perfettamente valida. È il modello basilare, che semplicemente coincide con il testo letterale «regex». Una «coincidenza» o «occorrenza» è la porzione di testo, o sequenza di byte o caratteri che il modello schematico ha scoperto corrispondere mediante un software che processa una regex.

    \b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b

    è già un modello schematico più complesso. Contiene una serie di lettere, numeri, punti, trattini, segni di percentuale e virgole, seguite da un segno e da un'altra serie di lettere, numeri e virgole e infine seguite da un singolo punto e due o più lettere. In altre parole: questo modello schematico descrive un indirizzo e-mail e mostra la formattazione applicata alle espressioni regolari in questa guida.

    Con la suddetta espressione regolare è possibile cercare in un testo la presenza di indirizzi e-mail o verificare se una determinata stringa assomiglia ad un indirizzo e-mail. Questa guida usa il termine «stringa» per indicare il testo a cui l'espressione regolare viene applicata. Il termine «stringa» o «stringa di caratteri» viene usata dai programmatori per indicare una sequenza di caratteri. In pratica, è possibile usare le espressioni regolari con qualsiasi tipo di dati a cui sia possibile accedere utilizzando una qualsiasi applicazione (editor, word processor, analizzatore etc.) o linguaggio di programmazione in uso.

    Differenti «motori» delle RegEx

    Il «motore» di una espressione regolare è una porzione di software in grado di processare espressioni regolari, tentando di far combaciare il modello schematico che gli viene fornito con una determinata stringa. In genere il motore è parte di una applicazione più estesa e non è accessibile direttamente. Piuttosto, l'applicazione viene richiamata quando è necessaria, assicurando che la corretta espressione regolare sia applicata al file o ai dati correnti.

    Come al solito nel mondo del software, differenti motori di espressioni regolari non sono tra loro pienamente compatibili. La sintassi e il comportamento di un particolare motore per espressioni regolari viene denominata «variante» (flavour). Questa guida copre solo le varianti più diffuse di motori per espressioni regolari, come quelle di:

    editor: EditPad (Pro|Lite), Emacs, MS Word, Notepad++, Libre/Apache/Open Office Writer, Vim;

    fogli di calcolo: Google Documenti – Fogli;

    database: MySQL, Oracle, PostgreSQL, SQLite;

    app e shell: Apache HTTPd, Awk, Find, Grep, Nginx, PowerGrep, PowerShell, Sed, ShellScript (Bash);

    linguaggi di programmazione: C,

    Enjoying the preview?
    Page 1 of 1