3 points par GN⁺ 14 시간 전 | 1 commentaires | Partager sur WhatsApp
  • 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, awk et grep, en utilisant aussi l’option -E de sed et grep, l’ensemble des fonctionnalités communes utilisables s’élargit, mais dans cette combinaison awk devient généralement le plus petit dénominateur commun
  • Emacs exige une barre oblique inverse pour +? ( ) { } |, et le sens de \s et \S diffè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, grep et Emacs, on peut assouplir un peu le critère de « partout »
  • Avec les versions GNU de sed, awk et grep, et en appliquant l’option -E à sed et grep, 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 awk sont généralement aussi prises en charge par les autres outils
    • À titre d’exception, les limites de mot s’écrivent \< et \> dans awk, et diffèrent de \b et \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 dans awk, ils doivent être précédés d’une barre oblique inverse
    • Les équivalents de \s et \S de awk sont \s- et \S- dans Emacs
  • Dans Emacs, \s et \S ne 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
  • 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, gawk prend 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-around peut être considéré comme une fonctionnalité avancée, et \d peut 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 à utiliser
    Au-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...

    • Cela devient encore plus amusant quand on écrit du Python qui génère des scripts shell contenant des expressions régulières
      On se retrouve sans cesse avec des règles d’échappement différentes qui s’empilent
    • Si l’on cherche un avantage un peu forcé, quand la cible de recherche est du code Elisp, le fait que ( et ) correspondent littéralement est légèrement pratique
    • Les expressions régulières auraient dû être un langage structuré, et non un méli-mélo de plusieurs DSL
  • L’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

    • Cette appréciation ne me paraît pas juste envers l’auteur
      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

    • regexp n’utilise pas re2 : c’est une implémentation séparée des mêmes concepts
  • Aprè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/...