Des expressions régulières qui fonctionnent « partout »
(johndcook.com)- Les expressions régulières varient selon les implémentations, tant par les fonctionnalités prises en charge que par la syntaxe ; un motif qui fonctionnait dans un outil peut donc échouer ou nécessiter des modifications dans un autre environnement
- Plus on est habitué à un environnement riche en fonctionnalités comme Perl, plus on rencontre souvent des problèmes de compatibilité ; si l’on tient compte aussi des ordinateurs où l’on n’a pas le droit d’installer de logiciels, il est plus sûr d’utiliser un sous-ensemble commun
- Si l’on définit « partout » de la façon la plus stricte, le périmètre devient si restreint qu’il ne reste guère que les littéraux, les classes de caractères
[…]et les caractères spéciaux de base comme. * ^ $ - Avec GNU
sed,awketgrep, en utilisant aussi l’option-Edesedetgrep, l’ensemble des fonctionnalités communes utilisables s’élargit, mais dans cette combinaisonawkdevient généralement le plus petit dénominateur commun - Emacs exige une barre oblique inverse pour
+? ( ) { } |, et le sens de\set\Sdiffère également ; pour employer la même expression régulière dans plusieurs outils, il faut donc aussi vérifier les syntaxes d’exception
Pourquoi la compatibilité des expressions régulières est difficile
- Le principal désagrément des expressions régulières vient des différences entre implémentations
- Une fonctionnalité prise en charge dans un outil peut être totalement absente dans un autre
- Même pour une même fonctionnalité, la syntaxe peut varier légèrement
- Perl est un environnement d’expressions régulières très riche en fonctionnalités ; certaines fonctions qui paraissent évidentes avec Perl peuvent manquer ailleurs
- On peut aussi utiliser des substituts proches de Perl dans d’autres outils, mais ce n’est pas standard, ce qui complique l’envoi à des collègues ou clients de code exécutable tel quel
- Si l’on tient compte des situations où il faut travailler sur un ordinateur où l’on ne peut pas installer de logiciel, il devient nécessaire de chercher un sous-ensemble de fonctionnalités d’expressions régulières qui fonctionne dans plusieurs environnements
- Plus on définit strictement « partout », plus les fonctionnalités utilisables diminuent
- Littéraux
- Classes de caractères
[…] - Caractères spéciaux
. * ^ $
Périmètre commun entre sed, awk, grep et Emacs
- En limitant les outils ciblés à
sed,awk,grepet Emacs, on peut assouplir un peu le critère de « partout » - Avec les versions GNU de
sed,awketgrep, et en appliquant l’option-Eàsedetgrep, la liste des fonctionnalités communes s’élargit- Les fonctionnalités d’expressions régulières des trois outils sont similaires
- Les fonctionnalités de
awksont généralement aussi prises en charge par les autres outils - À titre d’exception, les limites de mot s’écrivent
\<et\>dansawk, et diffèrent de\bet\B
- Emacs correspond à la plupart des fonctionnalités de
awk, mais avec des différences de syntaxe- Pour que
+ ? ( ) { } |jouent le même rôle que dansawk, ils doivent être précédés d’une barre oblique inverse - Les équivalents de
\set\Sdeawksont\s-et\S-dans Emacs
- Pour que
- Dans Emacs,
\set\Sne signifient pas espace/non-espace, mais commencent une classe de caractères- La classe
-désigne les espaces \s.désigne un caractère de ponctuation\S.désigne un caractère qui n’est pas de ponctuation
- La classe
- Selon ce critère, les fonctionnalités utilisables sont les suivantes
.^,$[…],[^…]*\w,\W,\s,\S- Les références arrière de
\1à\9 \b,\B?,+- L’alternative
| - Le nombre de répétitions
{n,m} - La capture
(...)
- Cependant,
gawkprend en charge les références arrière dans les chaînes de substitution, mais pas dans les expressions régulières elles-mêmes - Le
look-aroundpeut être considéré comme une fonctionnalité avancée, et\dpeut sembler être une fonctionnalité de base pour les chiffres, mais il n’est pas pris en charge par de nombreuses variantes d’expressions régulières
1 commentaires
Commentaires de Hacker News
Avec Emacs, c’est particulièrement pénible, car on a presque l’impression de devoir deviner ce qu’il faut échapper
Il existe bien une alternative appelée
rx[0], mais, en pratique, elle n’est pas vraiment agréable à utiliserAu-delà de la syntaxe des expressions régulières elle-même, des problèmes d’encodage et d’échappement apparaissent souvent au moment de l’utilisation concrète
Si l’on saisit une expression régulière dans un shell, il faut l’échapper correctement ; en Python, il faut vérifier qu’il s’agit bien d’une chaîne brute (raw string), et ainsi de suite
Malgré tout, le fait que la manière d’utiliser les expressions régulières dans la plupart des outils se situe dans une plage à peu près similaire tient presque du miracle moderne
[0]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Rx...
On se retrouve sans cesse avec des règles d’échappement différentes qui s’empilent
(et)correspondent littéralement est légèrement pratiqueL’auteur semble presque y arriver sans tout à fait le dire, mais il veut probablement dire qu’au final les expressions régulières de base POSIX fonctionnent partout
Avec toutefois la réserve que tout le monde n’a pas encore rattrapé la 8e édition de la Single Unix Specification, et que cette édition a légèrement modifié les BRE
Sans ce genre de réserve, il n’y aurait probablement même pas eu besoin d’écrire l’article
J’ai autrefois écrit un article de recherche sur les expressions régulières qui se correspondent de la même manière à la fois avec la sémantique gloutonne et la sémantique leftmost maximal
https://par.nsf.gov/servlets/purl/10534654
J’ai toujours été pointilleux sur la nécessité de préciser quel langage d’expressions régulières un outil accepte, et ce qu’il fait correspondre parmi une sous-chaîne arbitraire, un préfixe, un suffixe, la chaîne entière, une ligne ou une sous-chaîne dans une ligne
Il y a ici [les variantes les plus répandues][1], ainsi que PCRE et Python
Il m’a fallu un certain temps pour apprendre que certaines des anciennes formes que l’on voit dans des outils comme grep sont [spécifiées par POSIX][2]
[1]: https://cppreference.com/cpp/regex#Regular_expression_gramma...
[2]: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd...
Je voudrais partager les pages de Russ Cox sur les expressions régulières
Je pense que ce sont de bonnes ressources à lire
https://swtch.com/~rsc/regexp/
C’est pour ce genre de raisons que la RFC 9485, I-Regexp: An Interoperable Regular Expression Format, est importante
https://datatracker.ietf.org/doc/html/rfc9485
Le package regexp de la bibliothèque standard de Go utilise le moteur RE2, il ne prend donc pas en charge les références arrière
On peut les utiliser dans les substitutions, mais pas dans les correspondances
regexpn’utilise pas re2 : c’est une implémentation séparée des mêmes conceptsAprès avoir connu des frustrations similaires avec des moteurs de règles, des moteurs de templates et des moteurs de type IFTTT, j’ai créé une bibliothèque Rust pour JSONLogic, et j’utilise aussi des bindings pour d’autres langages
https://github.com/GoPlasmatic/datalogic-rs
La documentation de JSON Schema contient aussi un sous-ensemble recommandé d’expressions régulières
https://json-schema.org/understanding-json-schema/reference/...