Come viene effettivamente utilizzato Regex??

Contenuti

Regex, abbreviazione dell'espressione regolare, è spesso usato nei linguaggi di programmazione per abbinare i modelli nelle stringhe, cerca e sostituisci, convalida dell'input e riformattazione del testo. Imparare a usare correttamente Regex può rendere molto più facile lavorare con il testo.

Sintassi delle espressioni regolari, spiegato

Regex ha la reputazione di avere una sintassi orribile, ma è molto più facile scrivere che leggere. Come esempio, Ecco un'espressione regolare generale per un validatore e-mail conforme a RFC 5322:

(?:[a-z0-9!#$%&'*+/=?^_`~-]+(?:.[a-z0-9!#$%&'*+/=?^_`~-]+)*|"(?:[x01 ·-
x08x0bx0cx0e-x1fx21x23-x5bx5d-x7f]|[x01-x09x0bx0cx0e-x7f])*")
@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|[(?
:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-
9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[x01-x08x0bx0cx0e-x1fx21-x5ax53-x7f]|
[x01-x09x0bx0cx0e-x7f])+)])

Se sembra che qualcuno abbia colpito la faccia contro la tastiera, non sei solo. Ma sotto il cofano, tutto questo casino è in realtà la programmazione di un macchina a stati finiti. Questa macchina funziona per ogni personaggio, andare avanti e combinare secondo le regole che hai impostato. Molti strumenti online renderanno i diagrammi ferroviari, mostra come funziona la tua macchina Regex. Ecco la stessa regex in forma visiva:

Ancora molto confuso, ma è molto più comprensibile. È una macchina con parti in movimento che hanno regole che definiscono come tutto si adatta. Puoi vedere come qualcuno ha assemblato questo; non è solo un sacco di testo.

Primo: usa un debugger regex

Prima di cominciare, a meno che la tua Regex non sia particolarmente corta o tu non sia specificamente competente, dovresti usare un debugger online durante la scrittura e il test. Rende molto più facile capire la sintassi. Consigliamo Regex101 e RegExr, offrendo riferimenti e test della sintassi integrati.

Come funziona Regex??

Per adesso, concentriamoci su qualcosa di molto più semplice. Questo è un diagramma di Regulex per un'espressione regolare di corrispondenza e-mail molto breve (e sicuramente non conforme a RFC 5322):

Il motore Regex si avvia a sinistra e viaggia lungo le linee, corrispondenza dei caratteri man mano che procedi. Il gruppo # 1 corrisponde a qualsiasi carattere tranne un'interruzione di riga, e continuerà ad abbinare i caratteri fino a quando il blocco successivo non trova una corrispondenza. Per questo caso, si ferma quando gira a @ simbolo, il che significa che il Gruppo # 1 acquisisce il nome dell'indirizzo email e tutto ciò che segue corrisponde al dominio.

L'espressione regolare che imposta il Gruppo # 1 nel nostro esempio di email è:

(.+)

Le parentesi definiscono un gruppo di cattura, che dice al motore Regex di includere il contenuto della corrispondenza di questo gruppo in una variabile speciale. Quando esegui un'espressione regolare su una stringa, il risultato predefinito è la corrispondenza completa (per questo caso, tutte le email). Ma restituisce anche ogni gruppo di cattura, il che rende questa regex utile per estrarre i nomi dalle email.

Il punto è il simbolo di “Qualsiasi carattere tranne la nuova riga”. Questo corrisponde a tutto su una riga, quindi se hai passato questa email Regex un indirizzo come:

%$#^&%*#%$#^@gmail.com

corrisponderebbe %$#^&%*#%$#^ come il nome, anche se è ridicolo.

Il simbolo più (+) è una struttura di controllo che significa “corrispondono al carattere o al gruppo precedente una o più volte”. Assicurati che tutti i nomi corrispondano, e non solo il primo personaggio. Questo è ciò che crea il loop trovato nel diagramma della ferrovia.

Il resto di Regex è piuttosto semplice da capire:

(.+)@(.+..+)

Il primo gruppo si ferma quando colpisce il @ simbolo. Più tardi inizia il prossimo gruppo, che corrisponde di nuovo a parecchi caratteri finché non incontra un carattere punto.

Perché caratteri come i punti, parentesi e barre sono usate come parte della sintassi in Regrex, ogni volta che vuoi abbinare quei caratteri, deve uscire correttamente con una barra rovesciata. In questo esempio, per abbinare il periodo, abbiamo scritto . e l'analizzatore lo tratta come un simbolo che significa “abbinare un punto”.

Corrispondenza dei caratteri

Se hai personaggi non controllati nella tua Regex, il motore Regex assumerà che quei caratteri formeranno un blocco corrispondente. Come esempio, Regex:

lui + esso

Corrisponderà alla parola “Ciao” con qualsiasi numero e. È necessario sfuggire a qualsiasi altro carattere per farlo funzionare correttamente.

Regex ha anche classi di caratteri, che fungono da abbreviazione per un insieme di caratteri. Questi possono variare a seconda dell'implementazione Regex, ma questi pochi sono standard:

  • . – corrisponde a qualsiasi cosa tranne newline.
  • w – corrisponde a qualsiasi carattere di “parola”, comprese cifre e trattini bassi.
  • d – abbinare i numeri.
  • b – corrisponde ai caratteri degli spazi bianchi (In altre parole, spazio, tabulazione, nuova linea).

Questi tre hanno controparti maiuscole che invertono la loro funzione. Come esempio, D corrisponde a qualcosa di diverso da un numero.

Regex ha anche un set di caratteri. Come esempio:

[abc]

Abbinerà chiunque a, b, oh c. Questo agisce come un blocco e le parentesi sono solo strutture di controllo. In alternativa, puoi specificare un intervallo di caratteri:

[AC]

O negare il set, che corrisponderà a qualsiasi carattere che non è nel set:

[^a-c]

quantificatori

I quantificatori sono una parte importante di Regex. Ti permettono di abbinare catene dove non conosci le Esattamente formato, ma hai una buona idea.

il + L'operatore nell'esempio di posta elettronica è un quantificatore, in particolare il quantificatore “uno o più”. Se non sappiamo quanto è lunga una certa catena, ma sappiamo che è composto da caratteri alfanumerici (e non è vuoto), possiamo scrivere:

w+

Allo stesso tempo di +, C'è anche:

  • il * operatore, che corrisponde “zero o più”. Essenzialmente lo stesso di +, tranne che hai la possibilità di non trovare una corrispondenza.
  • il ? operatore, che corrisponde “zero o uno”. Ha l'effetto di rendere un personaggio facoltativo; O c'è o non c'è, e non corrisponderà più di una volta.
  • Quantificatori numerici. Questi possono essere un singolo numero come {3}, Che cosa significa “Esattamente 3 volte” o un intervallo come {3-6}. Puoi saltare il secondo numero per renderlo illimitato. Come esempio, {3,} significa “3 o più volte”. curiosamente, non posso saltare il primo numero, quindi se vuoi “3 tempi o meno”, dovrai usare un intervallo.

Quantificatori avidi e pigri

Sotto il cappuccio, il * e + gli operatori sono avaro. Corrisponde il più possibile e restituisce ciò che è necessario per iniziare il blocco successivo. Questo può essere un enorme ostacolo..

Ecco un esempio: diciamo che stai cercando di abbinare HTML o qualsiasi altra cosa con le parentesi graffe di chiusura. Il tuo testo di input è:

<div>Ciao mondo</div>

E vuoi abbinare tutto tra parentesi. Puoi scrivere qualcosa come:

<.*>

Questa è l'idea corretta, ma fallisce per un motivo cruciale: el motore Regex coincidono “div>Hello World</div>“Per la sequenza .*, e poi esegue il backup fino alla corrispondenza del blocco successivo, per questo caso, con parentesi chiusa (>). Speriamo che si tiri indietro solo per abbinare “div“, E poi ripeti di nuovo per abbinare il div di chiusura. Ma il backtracker corre dalla fine della catena e si fermerà alla parentesi finale, che finisce per abbinare tutto all'interno delle parentesi.

La risposta è rendere pigro il nostro quantificatore, il che significa che corrisponderà al minor numero di caratteri possibile. Sotto il cappuccio, questo in realtà corrisponderà solo a un carattere, e poi si espanderà per riempire lo spazio fino alla successiva corrispondenza del blocco, che lo rende molto più efficiente nelle grandi operazioni Regex.

Rendere pigro un quantificatore viene fatto aggiungendo un punto interrogativo direttamente dopo il quantificatore. Questo è un po' di confusione perché ? è già un quantificatore (ed è in realtà avido per impostazione predefinita). Per il nostro esempio HTML, la regex è fissata con questa semplice aggiunta:

<.*?>

L'operatore pigro può essere aggiunto a qualsiasi quantificatore, incluso +?, {0,3}?, e inclusivo ??. Anche se l'ultimo non ha effetto; perché stai comunque abbinando zero o un carattere, non c'è spazio per espandersi.

Raggruppamento e Lookaround

I gruppi in Regex hanno molti scopi. A livello base, abbina più tessere in un blocco. Come esempio, puoi creare un gruppo e poi usare un quantificatore sull'intero gruppo:

ba(Su)+

Questo raggruppa il “Su” ripetuto per corrispondere alla frase banana, e banananana, e così via. Senza il gruppo, il motore Regex corrisponderebbe più e più volte al carattere finale.

Questo tipo di gruppo con due parentesi singole è chiamato gruppo di acquisizione e lo includerà nell'output:

Se vuoi evitare questo e raggruppare i token solo per scopi di esecuzione, puoi usare un gruppo che non cattura:

ba(?:Su)

Il punto interrogativo (un carattere riservato) imposta un gruppo non standard e il carattere successivo imposta che tipo di gruppo è. Iniziare i gruppi con un punto interrogativo è l'ideale, perché altrimenti, se volessi abbinare il punto e virgola in un gruppo, Avrei bisogno di scappare da loro senza una buona ragione. Ma tu per sempre devi sfuggire ai punti interrogativi in ​​Regex.

Puoi anche nominare i tuoi gruppi, per comodità, quando lavoro con l'output:

(?'gruppo')

Puoi fare riferimento a questi nella tua Regex, che li fa funzionare in modo equivalente alle variabili. Puoi fare riferimento a gruppi senza nome con il token 1, ma questo va solo fino a 7, dopodiché dovrai iniziare a nominare i gruppi. La sintassi per fare riferimento a gruppi denominati è:

K{gruppo}

Questo si riferisce ai risultati del gruppo nominato, che può essere dinamico. Essenzialmente, controlla se il gruppo si presenta più volte ma non si preoccupa della posizione. Come esempio, questo può essere usato per abbinare tutto il testo tra tre parole identiche:

La classe di gruppo è dove troverai la maggior parte della struttura di controllo Regex, compresa la prospettiva. I lookahead assicurano che un'espressione debba corrispondere ma non includerla nel risultato. In un modo, è equivalente a un'istruzione if e non corrisponderà se restituisce false.

La sintassi per un lookahead positivo è (?=). Ecco un esempio:

Questo corrisponde alla parte del nome di un indirizzo e-mail in modo molto preciso, arresto dell'esecuzione sulla divisione @. Le ricerche Lookahead non utilizzano alcun carattere, quindi se vuoi continuare a correre dopo che un lookahead ha avuto successo, puoi ancora abbinare il carattere utilizzato in lookahead.

Allo stesso tempo delle prospettive positive, C'è anche:

  • (?!) – Lookaheads negativi, che assicurano un'espressione. no incontro.
  • (?<=) – Lookbehind positivos, che non sono supportati ovunque a causa di alcune limitazioni tecniche. Questi sono posizionati prima dell'espressione che vuoi abbinare e devono avere una larghezza fissa (In altre parole, nessun quantificatore tranne {number}. In questo esempio, potresti usare (?<=@)w+.w+ per abbinare la parte del dominio dell'e-mail.
  • (?<!) – Sguardi negativi indietro, che sono uguali agli sguardi posteriori positivi, ma negato.

Differenze tra i motori Regex

Non tutte le espressioni regolari sono uguali. La maggior parte dei motori Regex non segue alcuno standard specifico, e alcuni cambiano un po' le cose per adattarsi alla loro lingua. Alcune funzioni che funzionano in una lingua potrebbero non funzionare in un'altra.

Come esempio, le versioni di sed compilato per macOS e FreeBSD non supporta l'uso t per rappresentare un carattere di tabulazione. È necessario copiare manualmente un carattere di tabulazione e incollarlo nel terminale per utilizzare una tabulazione sulla riga di comando sed.

La maggior parte di questo tutorial è conforme a PCRE, il motore Regex predefinito utilizzato per PHP. Ma il motore JavaScript Regex è diverso: non supporta i gruppi di acquisizione denominati con virgolette (voglio le parentesi) e non posso fare ricorsione, tra l'altro. Anche PCRE non è completamente compatibile con versioni diverse, e ha molte differenze de Perl regex.

Ci sono troppe piccole differenze da elencare qui, quindi puoi usare questa tabella di riferimento per confrontare le differenze tra i vari motori Regex. Allo stesso tempo, Debugger Regex come Regex101 ti consente di cambiare i motori Regex, quindi assicurati di eseguire il debug usando il motore corretto.

Come eseguire Regex

Abbiamo discusso della parte corrispondente di regex, che costituisce la maggior parte di ciò che fa un'espressione regolare. Ma quando vuoi davvero eseguire la tua Regex, dovrai convertirlo in una regex completa.

Questo generalmente prende il formato:

/partita/g

Tutto all'interno delle barre è il nostro match. il g è un modificatore di modalità. Per questo caso, dice al motore di non smettere di funzionare dopo che è stata trovata la prima corrispondenza. Per trovare e sostituire Regex, dovrai spesso formattarlo come:

/trova/sostituisci/g

Questo sostituisce l'intero file. È possibile utilizzare i riferimenti del gruppo di acquisizione durante la sostituzione, il che rende Regex molto bravo a formattare il testo. Come esempio, questa regex corrisponderà a qualsiasi tag HTML e sostituirà le parentesi quadre standard con parentesi quadre:

/<(.+?)>/[1]/G

Quando funziona, il motore si abbinerà <div> e </div>, che ti permette di sostituire questo testo (e solo questo testo). Come potete vedere, l'HTML interno non è interessato:

Questo rende Regex molto utile per trovare e sostituire il testo. L'utilità della riga di comando per farlo è sed, che utilizza il formato base di:

sed '/trova/sostituisci/g' file > file

Questo viene eseguito in un file e inviato a STDOUT. Dovrai collegarlo a te stesso (come mostrato qui) per sostituire il file su disco.

Regex è anche compatibile con molti editor di testo e può davvero accelerare il tuo flusso di lavoro eseguendo operazioni batch.. Spingere, Atomo, e VS CodTutti hanno funzionalità di ricerca e sostituzione Regex integrate.

In ogni caso, Regex può essere utilizzato anche tramite programmazione e, generalmente, è integrato in molte lingue. L'esatta implementazione dipenderà dalla lingua, quindi dovresti consultare la documentazione per la tua lingua.

Come esempio, e JavaScript, regex può essere creato letteralmente o dinamicamente usando l'oggetto RegExp globale:

var re = nuova RegExp('abc')

Questo può essere utilizzato direttamente chiamando .exec() metodo dell'oggetto regex appena creato, o usando il .replace(), .match(), e .matchAll() metodi su stringhe.

Iscriviti alla nostra Newsletter

Non ti invieremo posta SPAM. Lo odiamo quanto te.