ES2015 ha introdotto molte nuove funzionalità nel linguaggio JavaScript, tra cui miglioramenti significativi alla sintassi delle espressioni regolari con i flag Unicode (/u
) e sticky (/y
). Ma lo sviluppo non si è fermato da allora. In stretta collaborazione con altri membri del TC39 (l'organismo di standard ECMAScript), il team di V8 ha proposto e co-progettato diverse nuove funzionalità per rendere le espressioni regolari ancora più potenti.
Al momento queste funzionalità sono in fase di proposta per l'inclusione nella specifica di JavaScript. Anche se le proposte non sono state completamente accettate, si trovano già nella fase 3 della procedura TC39. Abbiamo implementato queste funzionalità tramite un flag (vedi di seguito) per poter fornire tempestivamente un feedback in merito a progettazione e implementazione ai rispettivi autori della proposta prima della finalizzazione della specifica.
Questo post del blog ti offre un'anteprima di questo entusiasmante futuro. Se vuoi seguire gli esempi che verranno presentati in seguito, attiva le funzionalità sperimentali di JavaScript all'indirizzo chrome://flags/#enable-javascript-harmony
.
Acquisizioni con nome
Le espressioni regolari possono contenere i cosiddetti "gruppi", che possono acquisire una parte del testo corrispondente. Finora, gli sviluppatori potevano fare riferimento a queste acquisizioni solo tramite il relativo indice, che viene determinato dalla posizione dell'acquisizione all'interno del pattern.
const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'
Tuttavia, le espressioni regolari sono già notoriamente difficili da leggere, scrivere e manutenere e i riferimenti numerici possono aggiungere ulteriori complicazioni. Ad esempio, nei pattern più lunghi può essere complicato determinare l'indice di una determinata acquisizione:
/(?:(.)(.(?<=[^(])(.)))/ // Index of the last capture?
Inoltre, le modifiche a un pattern possono potenzialmente spostare gli indici di tutte le acquisizioni esistenti:
/(a)(b)(c)\3\2\1/ // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/ // All need to be updated.
Le acquisizioni con nome sono una funzionalità in arrivo che aiuta a mitigare questi problemi consentendo agli sviluppatori di assegnare nomi alle acquisizioni. La sintassi è simile a Perl, Java, .Net e Ruby:
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'
È possibile fare riferimento alle acquisizioni con nome anche tramite riferimenti a entità precedenti con nome e
String.prototype.replace
:
// Named backreferences.
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx'); // true
// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>'); // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd); // 'ba'
I dettagli completi di questa nuova funzionalità sono disponibili nella proposta di specifica.
Flag dotAll
Per impostazione predefinita, l'atomo .
nelle espressioni regolari corrisponde a qualsiasi carattere, ad eccezione dei caratteri di interruzione di riga:
/foo.bar/u.test('foo\nbar'); // false
Una proposta introduce la modalità dotAll, attivata tramite il flag /s
. In modalità dotAll, .
corrisponde anche ai terminatori di riga.
/foo.bar/su.test('foo\nbar'); // true
I dettagli completi di questa nuova funzionalità sono disponibili nella proposta di specifica.
Espressioni di escape delle proprietà Unicode
Con la consapevolezza Unicode introdotta in ES2015, ora esistono molti più caratteri che potrebbero essere considerati numeri, ad esempio il numero 1 cerchiato: ①; oppure considerati caratteri di parole, ad esempio il carattere cinese per la neve: 雪.
Nessuno di questi può essere associato a \d
o \w
. La modifica del significato di queste abbreviazioni potrebbe interrompere i pattern delle espressioni regolari esistenti.
Al loro posto, vengono introdotte nuove sequenze di escape per le proprietà.
Tieni presente che sono disponibili solo per le espressioni regolari Unicode, indicate dal flag /u
.
/\p{Number}/u.test('①'); // true
/\p{Alphabetic}/u.test('雪'); // true
L'inverso può essere abbinato a \P
.
/\P{Number}/u.test('①'); // false
/\P{Alphabetic}/u.test('雪'); // false
Il consorzio Unicode definisce molte altre proprietà, ad esempio per i simboli matematici o i caratteri hiragana giapponesi:
/^\p{Math}+$/u.test('∛∞∉'); // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな'); // true
L'elenco completo delle classi di proprietà Unicode supportate è disponibile nella vigente proposta di specifica. Per altri esempi, dai un'occhiata a questo articolo informativo.
Affermazioni lookbehind
Le asserzioni anticipate fanno parte della sintassi delle espressioni regolari di JavaScript fin dall'inizio. La loro controparte, le affermazioni lookbehind, sono finalmente in fase di introduzione. Alcuni di voi potrebbero ricordare che questa funzionalità fa parte di V8 già da un po' di tempo. Perfino gli assert lookbehind vengono utilizzati per implementare il flag Unicode specificato in ES2015.
Il nome descrive già abbastanza bene il suo significato. Offre un modo per limitare la corrispondenza di un pattern solo se è preceduto dal pattern nel gruppo di ricerca precedente. È disponibile sia con corrispondenza che senza:
/(?<=\$)\d+/.exec('$1 is worth about ¥123'); // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123'); // ['123']
Per maggiori dettagli, consulta il nostro post del blog precedente dedicato alle asserzioni lookbehind ed esempi nei casi di test V8 correlati.
Ringraziamenti
Questo post del blog non sarebbe completo senza menzionare alcune delle persone che hanno lavorato duramente per realizzare questo progetto: in particolare i campioni del linguaggio Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin e il guru di Irregexp Erik Corry; ma anche tutti gli altri che hanno contribuito alla specifica del linguaggio e all'implementazione di queste funzionalità in V8.
Ci auguriamo che queste nuove funzionalità per le espressioni regolari ti entusiasmino quanto noi.