Introduction

Lire la dernière version de l’article avec le style d’origine dans une nouvelle fenêtre.

Lire la dernière version de l’article avec le style d’origine dans une nouvelle fenêtre.

Aujourd’hui, nous allons vous présenter les expressions rationnelles, aussi appelées expressions régulières ou tout simplement regex (contraction de regular expression). Qu’est-ce donc ? C’est un outil puissant, mais pas toujours intuitif, notamment du fait d’une syntaxe assez abstruse, pour manipuler un texte, quel qu’il soit.

Imaginez qu’après avoir bouclé votre thèse, tout près de l’échéance, vous vous apercevez que toutes vos dates au format américain doivent être mises au format français, ou que les caractères chinois doivent être mis dans un style calligraphique, loin de la police par défaut, et cela sur 500 pages… Et si vous ne passez pas vos journées sur de la rédaction d’articles, imaginez qu’après de longues recherches, vous retrouvez des milliers de lignes de données textuelles dans un vieux format douteux, mais que vous devez les remettre d’aplomb pour les valoriser auprès de vos confrères dans un format interopérable…

Utiliser une expression rationnelle vous permettra de faire ces modifications très rapidement et de manière bien plus sûre que le simple rechercher/remplacer habituel de votre éditeur de texte favori.

Les développeurs informatiques connaissent généralement suffisamment bien cet outil, mais il gagnerait à être plus connu en dehors de ce domaine, puisqu’il s’agit d’un outil très utile aussi en édition, et en fait dans tous les domaines où l’on doit manipuler du texte (vérification, recherche ou modification).

Ce court article est là pour présenter les possibilités qu’offrent les expressions rationnelles, il ne s’agit pas d’un tutoriel (la Toile en regorge…), mais de quelques illustrations variées pour tenter de démontrer leur utilité.

Tout d’abord, si vous écrivez vos textes avec un logiciel (traitement de texte, publication assistée par ordinateur, etc.), il est possible que certaines modifications soient automatisées ou préconfigurées pour un appel ponctuel rapide. Dans tous les cas, certains logiciels permettent d’avoir accès à ces outils (parfois sous d’autres noms, comme grep sur InDesign). Il est aussi possible d’installer des extensions pour cela sur vos navigateurs, si vous avez besoin de faire des recherches plus fines sur la Toile.

Contexte

Dès lors que vous devez faire une recherche ou une modification d’une expression non littérale (comme pourrait l’être un caractère précis), mais sur une expression composée d’éléments abstraits ou variables, possédant une certaine logique, nous allons devoir utiliser un modèle (ou motif, une formule décrivant l’expression rationnelle ; en anglais pattern). Ce modèle permettra d’utiliser des caractères particuliers pour désigner par exemple des ensembles (tous les chiffres, toutes les lettres, etc.), leur nombre d’occurrences, leur structure, les éléments nécessaires, facultatifs, etc.

Plus généralement, dès que vous avez besoin de trouver un modèle de texte précis, ou de modifier un modèle par un autre, plusieurs choix s’offrent à vous :

  • Vous pouvez tout faire « à la main », mais c’est très chronophage et le taux d’erreur est rarement satisfaisant, mais pour un texte très court, c’est parfois très bien !
  • Vous pouvez demander à votre logiciel de gérer cela pour vous (selon votre maîtrise de ce dernier et ses propres possibilités), c’est généralement très bien, mais limité par ce que le logiciel propose déjà, donc plus le cas sera complexe, moins ce sera possible !
  • Vous pouvez demander à votre collègue informaticien (terme que les informaticiens utilisent rarement entre eux…) de faire cela pour vous, mais vous n’en aurez pas toujours un de disponible.
  • Vous pouvez apprendre quelques bases des expressions rationnelles pour accroître votre indépendance technique et vous ouvrir tout un nouvel univers de possibilités textuelles (en plus d’éprouver un certain sentiment de fierté) !

 

Illustrations

Conversion du séparateur décimal

Vous désirez convertir des nombres décimaux en modifiant le séparateur (virgule en français, point en anglais, notamment).

  • Rechercher simplement les nombres à point :
    • rechercher : \d+\.\d+\d signifie l’ensemble n’importe quel chiffre, + est le quantificateur au moins 1 fois et \. le caractère point (. signifie quant à lui n’importe quel caractère).
  • Rechercher les nombres à point ou à virgule :
    • rechercher : \d+(\.|,)\d+| est la coordination ou (alternative), les différents choix étant entre parenthèses (…) pour bien structurer et préciser les limites de l’alternative (en plus d’en faire un groupe…).
  • Remplacer les nombres à point par des nombres à virgule :
    • rechercher : (\d+)\.(\d+) où les deux blocs précédents, de part et d’autre du point, sont mis entre parenthèses, pour en faire des groupes de capture (ici numérotés automatiquement) auxquels on pourra se référer dans le remplacement ;
    • remplacer : $1,$2$n se réfère au groupe de capture n, donc ici les groupes 1 et 2 de la recherche associée, et , est la virgule qui se substitue donc au point.

Unifier des espaces

Vous désirez unifier les espaces, c’est-à-dire ramener à l’unité ces espaces successives (terme féminin en typographie) parfois hétérogènes (espaces simples, insécables, tabulation…).

  • rechercher : \s+\s représente l’ensemble n’importe quelle espace – simple, insécable, fine, etc. ;
  • remplacer : où il se trouve une seule espace.

Ajout d’espace insécable devant des ponctuations doubles

Vous désirez ajouter en français une espace fine insécable devant certaines ponctuations doubles (l’orthotypographie est un peu plus complexe, mais c’est un exemple).

  • rechercher : \s*([?!;:]) où ce qui se trouve entre les crochets […] est une classe de caractères, ici composée de quatre ponctuations doubles, classe elle-même incluse dans un groupe, précédé de n’importe quelle espace (\s), existant ou non (quantificateur *) ;
  • remplacer :  $1 où l’espace fine insécable placée avant le rappel au groupe de capture 1 est important.

Convertir des formats de date

Vous désirez convertir des dates à l’américaine (mois/jour/année) en dates à la française (jour/mois/année).

  • rechercher : (?<mois>\d+)/(?<jour>\d+)/(?<année>\d+) où nous avons trois groupes de captures (ici nommés grâce à ?<nom> à l’ouverture du groupe) formés de nombres décimaux séparés par le caractère / ;
  • remplacer : ${jour}/${mois}/${année} où nous intervertissons les deux premiers groupes des jours et des mois (on se réfère à présent au groupe nommé à nouveau par $, mais suivi du nom – entre accolades {…} – et non plus du numéro implicite).

Rechercher des scripts particuliers

Vous désirez trouver des caractères plus particuliers, notamment dans un texte multilingue.

  • Rechercher tous les caractères chinois (lato sensu : chinois, japonais, coréen), et les insérer entre des balises pour leur appliquer un style particulier, par exemple pour transformer le texte suivant :

le conte 娇娜 (嬌娜) est tiré de l’œuvre 聊斋志异 (聊齋誌異)

en un texte mieux formaté :

le conte <span class="chinois">娇娜</span> (<span class="chinois">嬌娜</span>) est tiré de l’œuvre <span class="chinois">聊斋志异</span> (<span class="chinois">聊齋誌異</span>)

    • rechercher : \p{Script=Han}+\p{Script=Han} est une propriété Unicode précisant l’ensemble des caractères appartenant au script han (« chinois »).
    • remplacer : <span class="chinois">$0</span> où le groupe de capture 0 correspond à la totalité de l’expression.
  • Rechercher tous les caractères combinants pas toujours faciles à détecter (diacritiques modifiant d’autres caractères, etc.) :
    • rechercher : \p{M}\p{…} est une propriété Unicode, ici précisant l’ensemble des caractères combinants.

Formater un segment de texte en XML

Si vous désirez formater un segment de texte qui suit une certaine logique (plus ou moins variable) au format XML, par exemple transformer le segment suivant (comportant quelques caractères combinants) :

fra     endurer     /ɑ̃.dy.ʁe/     [ɒ̃d̪yˈʁe]

en un bloc XML de cette forme :

<mot langue="fra">
  <orthographe script="lat">endurer</orthographe>
  <phonologie script="api">ɑ̃.dy.ʁe</phonologie>
  <phonétique script="api">ɒ̃d̪yˈʁe</phonétique>
</mot>
  • rechercher : (?<langue>\w+)\s+(?<orthographe>\w+)\s+/(?<phonologie>[\p{L}\p{M}.]+)/\s+\[(?<phonétique>[\p{L}\p{M}]+)\]\w représente l’ensemble n’importe quelle lettre, \p{L} la propriété Unicode n’importe quelle lettre (ils sont un peu différents…), et les crochets littéraux ([ et ]) sont là aussi protégés par \ ;
  • remplacer : <mot langue="$langue">\n  <orthographe script="lat">$orthographe</orthographe>\n  <phonologie script="api">$phonologie</phonologie>\n  <phonétique script="api">$phonétique</phonétique>\n</mot>\n est le saut de ligne.

Quelques explications

L’usage de la barre oblique inversée (antislash en anglais) signifie que le caractère qui suit est à prendre dans un sens particulier… Comme dans ce langage, il existe des caractères spéciaux, appelés opérateurs (ou métacaractères) – par opposition aux caractères littéraux –, comme ce + qui n’est pas le caractère « + » mais un quantificateur (un type d’opérateur) simple (stipulant que l’expression qui précède doit être présent au moins 1 fois), ou bien ce . qui est le caractère joker (n’importe quel caractère), il est nécessaire d’ajouter devant eux ce \ pour les distinguer des caractères littéraux. Ainsi, \+ signifie littéralement « + », de même que \. signifie littéralement « . ».
Néanmoins, ce n’est pas si simple, car nous avons aussi vu dans ce petit exemple que \d ne signifie pas littéralement « d ». La règle du \ change pour désigner ces classes de caractères, et là la lettre qui suit est un moyen mnémotechnique (pour les anglophones…) de savoir à quelle classe de caractères il fait référence.

Présentons quelques opérateurs utiles (pour la plupart vus lors des illustrations) :

  • | est la conjonction de coordination ou (alternative entre plusieurs options) ;
  • + permet de quantifier à au moins 1 fois l’expression précédente ;
  • * permet de quantifier à au moins 0 fois l’expression précédente ;
  • ? permet de quantifier à au plus 1 fois l’expression précédente ;
  • { et } permettent de préciser davantage les occurrences (x{7,9} permet de stipuler « x » entre 7 et 9 fois, x{7,} au moins 7 fois, x{,9} au plus 9 fois et x{9} exactement 9 fois) ;
  • ( et ) permettent de faire des groupes de capture (pour structurer, notamment avec les quantificateurs, et pour s’y référer plus tard…) :
    • (…) permet de faire des groupes de capture numérotés implicitement et $n de s’y référer ensuite ;
    • (?<nom>…) permet de faire des groupes de capture nommés explicitement et ${nom} de s’y référer ensuite (la syntaxe peut grandement varier…) ;
  • [ et ] permettent de former des classes de caractères ([xyz]+ permet de stipuler « x », « y » ou « z » au moins 1 fois) ;
  • - permet, dans une classe de caractères formée par […], de former une plage entre 2 caractères – adresses Unicode comprises, avec \u ([0-9] correspond à tous les chiffres occidentaux, [\u31c0-\u31e3] correspond aux traits des caractères chinois) ;
  • ^ permet, en début d’expression, de dire qu’il s’agit du début de la ligne, ou, dans une classe de caractères formée par […], de faire la négation de ce qui suit, et ainsi d’obtenir le complémentaire ;
  • $ permet, en début d’expression, de dire qu’il s’agit de la fin de la ligne ;
  • . est le joker (n’importe quel caractère) ;
  • \n est le saut de ligne (newline) (voire parfois \r\n sur Windows) ;
  • \t est la tabulation ;
  • \w est la classe de caractères des lettres (word) ;
  • \d est la classe de caractères des chiffres (decimal) ;
  • \s est la classe de caractères des espaces (space) ;
  • la version majuscule de ces classes de caractères est leur propre négation (\W : tout sauf lettre, \D : tout sauf chiffre, \S : tout sauf espace) ;
  • \p permet de déclarer une propriété Unicode (properties, la syntaxe peut grandement varier…) :
    • \p{L} est la propriété des lettres (letter) :
      • \p{Ll} est la propriété des lettres minuscules (letter lowercase) ;
      • \p{Lu} est la propriété des lettres majuscules (letter uppercase) ;
    • \p{N} est la propriété des nombres (number) ;
    • \p{M} est la propriété des caractères combinants (modifier) ;
    • \p{P} est la propriété des ponctuations (punctuation) ;
    • \p{S} est la propriété des symboles (symbol) ;
    • \p{Z} est la propriété des espaces…

Remarques

Il existe encore de nombreuses fonctionnalités, comme des conditions variées (« seulement si telle expression existe avant ou après », etc.), des récursions…

Notons qu’il existe différents moteurs d’expressions rationnelles, avec des différences parfois significatives entre eux (mais il existe quand même une très bonne base commune, rassurez-vous !), et les logiciels incluant cet outil auront généralement choisi un de ces moteurs, sans d’ailleurs forcément y avoir inclus toutes les fonctionnalités de ce dernier (qui peuvent aller très loin…).

Un bon site que je conseille pour tester ses expressions rationnelles est regex101.com. Il permet de tester les expressions, avec différents moteurs, d’avoir des informations colorées, des indications explicites, etc. ! Pour les plus curieux, une bonne référence reste regular-expressions.info !

Conclusion

Voilà pour cette présentation succincte. Son intérêt était de montrer à des profanes qu’un outil puissant se cache parfois dans leurs logiciels quotidiens, ou qu’il est aisément disponible (site, éditeur de texte…). Je ne m’attends évidemment pas à ce que vous puissiez l’utiliser comme si c’était votre langue maternelle dès la fin de la lecture de ce mini-article, mais si l’existence de ce formidable outil reste dans un coin de votre mémoire et que vous vous en souvenez le jour où il pourra vous être utile, alors cet article aura joué son rôle !

Benjamin Galliot (équipe informatique) – 9 mai 2023

Aller au contenu principal