Opérations booléennes avec les Expressions Régulières

Mon collègue Martial Bornet vient de publier un excellent livre sur les Expressions Régulières (Regex). C’est important de connaître les Regex. Powershell et .NET permettent de les utiliser comme nous allons le voir dans cet article, donc je vous conseille son livre car, car bien connaître les expressions régulières permet souvent de se sortir de situations compliquées et rendre nos chers scripts Powershell bien plus simples.

Les Regex permettent de chercher, comparer et manipuler des strings, et pour illustrer tout ça, nous allons voir comment faire des opérations booléennes avec des expressions régulières.

Petit rappel:

Une opération booléenne est une opération de logique qui utilise les opérateurs Et (-And), Ou (-Or) et not (!) pour vérifier la véracité d’une expression.

Par exemple:

  • L’expression « A et B » est vraie si A est vrai et B est vrai
  • « A ou B » est vraie si A est vrai ou B est vrai
  • !A est vrai si A est égal a 0 ou a null.

Voyons ça avec des exemples concrets.

En Powershell pour savoir si une chaîne de caractères contient une substring je pourrais appeler la méthode Contains, par exemple:

nous pourrions aussi utiliser une opération logique pour vérifier qu’une chaîne contient deux mots: « Hello » et « World »

Mais comment extraire le texte entre « Hello » et « World dans « Hello Magic World »‘, et ne le faire que si le texte est entouré de « Hello » ET de « World ».

Nous pourrions envisager un Split, et vérifier que les éléments 0 et 2 contiennent les chaînes « Hello » et « World », du coup l’élément 1 contient ce qu’on veut extraire, ainsi:

Mais en fait ce split du caractère espace n’est valable que si ce qu’il y a entre Hello et World ne contient pas d’espaces, car le cas échéant ça ne fonctionnerait plus.

Avec plusieurs espaces on devrait utiliser une autre méthode: IndexOf, ainsi:

Vous voyez, dès qu’on veut faire un peu plus, le code devient plus complexe.

Voici une autre façon de faire, en utilisant une expression régulière:

et en une seule ligne s’il vous plaît:

et le résultat, c’est Magic, bien sur.

Voyons un peu cette expression régulière de plus près.

  • (?<=Hello) : est un Positive lookbehind, en français une recherche de droite à gauche, on peut la reconnaître grace au caractère « < » qui nous montre la direction arrière.
  • (?=World) est un Positive Lookahead, une recherche de gauche vers la droite, ici on cherche la première occurrence de « Word ».
  • (.+) est un groupe de capture, c’est le texte qu’on veut extraire: « . » veut dire n’importe quel caractère à part un newline (\n) et + veut dire 1 ou plusieurs fois.

Ce regex peut être interprété ainsi:

Extraire un ou plusieurs caractères si ces caractères sont précédés par Hello et suivis par World.

Voici un Regex permettant d’évaluer une chaîne si elle contient au moins une de deux substrings prédéfinies:

Voyons le Regex:

  • (?=.*One) Cherche depuis le début de la chaîne le mot « One »
  • | opérateur Or (ou)
  • (?=.*Two) Cherche depuis le début de la chaîne le mot « Two »

Si l’une des deux opérandes est vraie, la valeur de $matches[0] est rendu, ce qui est dans ce cas la chaîne complète.

A noter qu’il est important de chercher la chaîne complète (le ‘.*’ après le ‘=’) car Regex se souvient de sa position, et nous voulons par exemple que le résultat soit le même pour la chaîne: « two OR one ».

Voyons maintenant une opération NOT

  • ^ recherche depuis le début
  • (?!.*one.*) one ne doit pas apparaître ni seul, ni accompagné d’autres caractères au début ou à la fin
  • (?!.*two.*) même chose que ‘one’
  • le tout avec .* c’est à dire qu’on s’attend à la présence d’autres caractères dans la chaîne.

En plus simple peut-être:  Ni ( *one*) Ni (*two*) AVEC *

Il existe également un token de recherche négative arrière, le negative lookbehind: (?<!….) mais pour celui là je vous laisse le découvrir dans le livre de Martial 🙂

Voici un lien très utile lorsqu’on veut tester des regex: https://regex101.com/