Strumenti di testo e di uso quotidiano · Text Toolkit
Da Kleene a JavaScript: una breve storia delle espressioni regolari
· Sfondo
espressioni regolari javascript storia dell'informatica
Ripercorre le espressioni regolari dalla teoria degli automi degli anni '50 attraverso ed, grep e Perl fino al sapore JavaScript in ogni browser, spiegando perché la sintassi appare così e quali funzionalità sono arrivate quando.
Lo strano linguaggio che tutti conoscono a metà: perché la sintassi regex sembra antica e incoerente
Le espressioni regolari sembrano un linguaggio assemblato attraverso le epoche perché sostanzialmente è quello che sono. Un nucleo compatto di alternanza, ripetizione e raggruppamento è cresciuto dalla notazione matematica ai comandi dell'editor, ai filtri della riga di comando e alle funzionalità del linguaggio di programmazione. La punteggiatura è sopravvissuta mentre ciascun host aggiungeva le proprie comodità, vincoli e terminologia.
Questa storia spiega perché un modello può sembrare familiare ma comportarsi diversamente tra grep, Perl, Python e JavaScript. “Regex” è un nome di famiglia, non una grammatica universale. Per un analista autodidatta, la lezione utile non è memorizzare ogni dialetto, ma identificare il motore, i flag e le regole di sostituzione prima di fidarsi di uno schema preso in prestito.
Gli eventi regolari di Kleene: la matematica degli automi finiti degli anni '50 che ci ha dato la stella
Il lavoro di Stephen Cole Kleene sugli automi finiti e sugli “eventi regolari” ha fornito la base teorica negli anni ’50. La sua notazione descriveva insiemi di sequenze di simboli utilizzando operazioni tra cui unione, concatenazione e chiusura. L’operazione di chiusura è diventata la stella di Kleene: `A*` significa zero o più ripetizioni tratte da A, non semplicemente “ripeti una o più”.
I linguaggi regolari formali riconosciuti dagli automi finiti sono più ristretti di molti costrutti ora venduti sotto l'etichetta regex. I riferimenti all'indietro, ad esempio, possono esprimere condizioni che vanno oltre quel modello classico. I motori moderni preservano quindi il nome storico e gran parte della notazione mentre implementano linguaggi di pattern le cui capacità e strategie di esecuzione si estendono oltre l’oggetto matematico originale di Kleene.
Thompson, ed e grep: come l'espressione regex è entrata nell'editing di testo alla fine degli anni '60 e all'inizio degli anni '70 negli strumenti Unix
Ken Thompson ha collegato la teoria agli strumenti di testo funzionanti. Il suo articolo 1968 Communications of the ACM descriveva la compilazione di espressioni regolari in codice macchina per la ricerca di testo, e il suo precedente lavoro di editore ha contribuito a collocare la corrispondenza dei modelli all'interno del lignaggio Unix. L'editor `ed` utilizzava espressioni regolari nei comandi che selezionavano e trasformavano le righe corrispondenti.
Il nome `grep` deriva da un comando `ed` comunemente reso come `g/re/p`: seleziona globalmente le righe che corrispondono a un'espressione regolare e stampale. Il primo grep non era la raccolta odierna di opzioni GNU e successivamente i moduli POSIX di base ed estesi differiscono. Il cambiamento duraturo è stato pratico: un piccolo linguaggio simbolico è diventato un'interfaccia quotidiana per la ricerca di testo.
Perl e PCRE: le estensioni che hanno aggiunto quantificatori non golosi, lookaround e la sintassi copiata dalla maggior parte degli strumenti oggi
Perl ha creato un linguaggio di pattern più ricco centrale per la programmazione generica. Attraverso le sue versioni, i programmatori hanno riscontrato gruppi di cattura, riferimenti all'indietro, asserzioni, quantificatori pigri e modificatori di pattern in un ecosistema altamente visibile. La documentazione Perl 5 registra costrutti come `*?` per la corrispondenza minima e `(?=...)` per un lookahead positivo, insieme a molte funzionalità assenti nei vecchi moduli Unix.
È più sicuro dire che Perl abbia reso popolare questo stile piuttosto che attribuirgli il merito di aver inventato ogni estensione. PCRE ha deliberatamente offerto una sintassi compatibile con Perl, mentre altri motori hanno adottato idee selezionate e ne hanno rifiutate altre. La punteggiatura condivisa può nascondere semantiche, comportamenti Unicode o prestazioni diversi. "Simile a Perl" descrive quindi un'ampia influenza, non una garanzia che un modello Perl sia portabile.
Perl ha reso popolare un linguaggio di pattern pratico più ampio; motori successivi presi in prestito selettivamente
JavaScript ha standardizzato i propri oggetti `RegExp` e la sintassi letterale, come `/pattern/gi`, per i programmi in esecuzione nei browser e altri ambienti ECMAScript. La sua caratteristica include gruppi di cattura e non cattura, riferimenti all'indietro, lookahead, quantificatori pigri e classi di caratteri. Le edizioni successive hanno aggiunto gruppi di cattura denominati e asserzioni lookbehind nella specifica ES2018.
JavaScript non è PCRE o Python con delimitatori diversi. La disponibilità delle funzionalità dipende dall'edizione ECMAScript implementata dal motore e i flag fanno parte del comportamento piuttosto che della decorazione. La guida alle espressioni regolari di MDN è il riferimento pratico rilevante per la sintassi del browser, ma anche esempi di JavaScript validi possono fare affidamento su flag che una particolare interfaccia non espone.
JavaScript ha ottenuto gruppi con nome e lookbehind in ES2018, ma motori e flag differiscono ancora
I browser inseriscono un motore di espressioni regolari JavaScript accanto al normale lavoro di testo. Una pagina può compilare un modello, contare le corrispondenze e passarlo a `String.prototype.replace` senza inviare il testo a un servizio regex specializzato. Questa disponibilità rende possibile un'interfaccia di ricerca e sostituzione lato browser, sebbene la pagina circostante debba comunque essere ispezionata separatamente per rivendicazioni sulla privacy più ampie.
L'implementazione di ToolAcre chiama `new RegExp` all'interno di `compilePattern`, rileva gli errori di compilazione e restituisce un errore invece di lanciare un'eccezione. `findReplace` conta le corrispondenze prima di applicare l'operazione di sostituzione standard. Di conseguenza, i token di sostituzione JavaScript come i riferimenti di acquisizione seguono la stringa host API; la sintassi regex e la sintassi sostitutiva sono linguaggi correlati ma distinti.
Ciò che questo non copre: la teoria del linguaggio formale oltre le nozioni di base e le prestazioni interne del motore
Questa breve storia non dimostra l'equivalenza tra motori pratici e automi finiti, sondaggi algoritmi di esecuzione regex o classificazione delle implementazioni in base alla velocità. Il backtracking, le tecniche del tempo lineare e i modelli patologici meritano un trattamento separato. La guardia ToolAcre rileva gli errori di sintassi, ma non rileva un'espressione valida che esegue un backtracking eccessivo e blocca il thread principale del browser.
Né la sequenza temporale assegna ogni metacarattere a un singolo inventore. Le funzionalità del software spesso arrivavano attraverso documenti, editori, versioni linguistiche e reimplementazioni compatibili piuttosto che attraverso un passaggio diretto. Le fonti supportano traguardi specifici; non giustificano la storia più semplice secondo cui un prodotto ha creato la moderna regex all'ingrosso o che i sapori successivi hanno ereditato un comportamento identico.
Il punto è che la modalità regex di Text Toolkit è JavaScript, quindi i pattern della documentazione del browser funzionano come scritti
L'eredità pratica è visibile in ToolAcre: attiva Regex e il testo di ricerca viene compilato dal motore JavaScript del browser. Lasciando Regex disattivato i metacaratteri verranno sottoposti a escape, rendendo la ricerca letterale. La parola intera racchiude l'espressione con i confini ASCII in stile ``, mentre la distinzione tra maiuscole e minuscole controlla se il flag `i` accompagna il flag globale sempre presente `g`.
Quest’ultimo dettaglio corregge la promessa generale dello schema secondo cui i modelli di documentazione del browser funzionano come scritto. ToolAcre non espone flag multilinea, punto tutto, permanenti o Unicode, quindi gli esempi che richiedono `m`, `s`, `y`, `u` o `v` necessitano di adattamento e alcuni non possono essere riprodotti lì. Utilizza lo strumento per testare i pattern JavaScript supportati, leggere il conteggio delle sostituzioni e annullare prima di perfezionare.