Fonctionnalités à venir pour les expressions régulières

Jakob Gruber
Yang Guo

ES2015 a introduit de nombreuses nouvelles fonctionnalités dans le langage JavaScript, y compris des améliorations significatives de la syntaxe des expressions régulières avec les indicateurs Unicode (/u) et persistants (/y). Mais le développement n'a pas cessé depuis. En étroite collaboration avec les autres membres de TC39 (organisme de normes ECMAScript), l'équipe V8 a proposé et co-conçu plusieurs nouvelles fonctionnalités pour rendre les expressions régulières encore plus puissantes.

L'inclusion de ces fonctionnalités dans la spécification JavaScript est actuellement proposée. Même si les propositions n'ont pas été entièrement acceptées, elles en sont déjà à l'étape 3 du processus TC39. Nous avons mis en œuvre ces fonctionnalités en les affichant à l'aide d'un indicateur (voir ci-dessous) afin de pouvoir transmettre rapidement aux auteurs de propositions respectifs leurs commentaires sur la conception et l'implémentation avant que la spécification ne soit finalisée.

Cet article de blog vous donne un aperçu de cet avenir passionnant. Si vous souhaitez suivre les exemples à venir, activez les fonctionnalités JavaScript expérimentales sur chrome://flags/#enable-javascript-harmony.

Captures nommées

Les expressions régulières peuvent contenir des captures (ou groupes) qui peuvent capturer une partie du texte correspondant. Jusqu'à présent, les développeurs ne pouvaient faire référence à ces captures qu'à partir de leur indice, déterminé par la position de la capture dans le modèle.

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'

Cependant, les expressions régulières sont déjà connues pour être difficiles à lire, à écrire et à gérer, et les références numériques peuvent entraîner des complications. Par exemple, dans le cas de modèles plus longs, il peut être difficile de déterminer l'indice d'une capture particulière:

/(?:(.)(.(?<=[^(])(.)))/  // Index of the last capture?

Pire encore, les modifications apportées à un schéma peuvent potentiellement modifier les index de toutes les captures existantes:

/(a)(b)(c)\3\2\1/     // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/  // All need to be updated.

Les captures nommées sont une fonctionnalité à venir qui permet d'atténuer ces problèmes en permettant aux développeurs d'attribuer des noms aux captures. La syntaxe est semblable à celle de Perl, Java, .Net et 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'

Les captures nommées peuvent également être référencées par des références arrière nommées et via 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'

Vous trouverez tous les détails sur cette nouvelle fonctionnalité dans la proposition de spécification.

indicateur dotAll

Par défaut, l'atome . dans les expressions régulières correspond à n'importe quel caractère, à l'exception des sauts de ligne:

/foo.bar/u.test('foo\nbar');   // false

Une proposition introduit le mode dotAll, activé via l'indicateur /s. En mode dotAll, . correspond également aux sauts de ligne.

/foo.bar/su.test('foo\nbar');  // true

Vous trouverez tous les détails sur cette nouvelle fonctionnalité dans la proposition de spécification.

Échappements des propriétés Unicode

Avec la prise en compte d'Unicode introduite dans ES2015, de nombreux autres caractères peuvent être considérés comme des nombres, par exemple le chiffre entouré d'un cercle, un:1, ou considérés comme des caractères de mot, comme le caractère chinois de la neige : 雪.

Aucun de ces éléments ne peut être mis en correspondance avec \d ni \w. Si vous changez la signification de ces raccourcis, vous rompreriez les modèles d'expression régulière existants.

À la place, de nouvelles séquences d'échappement de propriété sont introduites. Notez qu'elles ne sont disponibles que pour les expressions régulières compatibles avec Unicode indiquées par l'indicateur /u.

/\p{Number}/u.test('①');      // true
/\p{Alphabetic}/u.test('雪');  // true

L'inverse peut être mis en correspondance avec \P.

/\P{Number}/u.test('①');      // false
/\P{Alphabetic}/u.test('雪');  // false

Le consortium Unicode définit de nombreuses autres propriétés, par exemple pour les symboles mathématiques ou les caractères hiragana japonais:

/^\p{Math}+$/u.test('∛∞∉');                            // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな');  // true

La liste complète des classes de propriétés Unicode compatibles est disponible dans la proposition de spécification actuelle. Pour voir d'autres exemples, consultez cet article informatif.

Assertions Lookbehind

Les assertions Lookahead font partie de la syntaxe d'expression régulière de JavaScript depuis le début. Leurs assertions équivalentes, les assertions Lookbehind, sont enfin introduites. Certains d'entre vous se souviennent peut-être que cela fait déjà partie de V8 depuis un certain temps. Nous avons même utilisé des assertions Lookbehind en arrière-plan pour implémenter l'indicateur Unicode spécifié dans ES2015.

Ce nom décrit déjà assez bien sa signification. Elle permet de limiter la correspondance d'un modèle uniquement s'il est précédé du motif dans le groupe Lookbehind. Il existe deux types de correspondance:

/(?<=\$)\d+/.exec('$1 is worth about ¥123');  // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123');  // ['123']

Pour en savoir plus, consultez notre article de blog précédent consacré aux assertions searchbehind, ainsi que des exemples dans les scénarios de test V8 connexes.

Remerciements

Cet article de blog ne serait pas complet sans mentionner certaines des personnes qui ont travaillé dur pour y parvenir: en particulier les champions de langue Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin et Irregexp guru Erik Corry.

Nous espérons que ces nouvelles fonctionnalités liées aux expressions régulières vous plaisent autant que nous !