Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. C# 10
  3. Expressions régulières
Extrait - C# 10 Développez des applications Windows avec Visual Studio 2022
Extraits du livre
C# 10 Développez des applications Windows avec Visual Studio 2022
4 avis
Revenir à la page d'achat du livre

Expressions régulières

Introduction

Les expressions régulières ont pour but de rechercher des chaînes de caractères dans une autre chaîne de caractères à l’aide de modèles déterminés. Ces modèles sont définis sous forme d’objets de type string en une syntaxe précise comme pour un langage spécifique. L’espace de noms System.Text.RegularExpressions expose les classes utilisées pour travailler avec les expressions régulières comme Regex, Match ou Group.

Les expressions régulières permettent de réaliser différentes opérations sur les objets de type string. Vous pouvez par exemple identifier les mots en doublon, changer la casse, séparer les différents éléments d’une URL ou vérifier que le format correspond bien à un modèle.

L’utilisation des expressions régulières se fait essentiellement avec la classe Regex qui contient des méthodes statiques et qui peut aussi être instanciée. Une expression régulière ressemble de près à un objet string. La différence est qu’il contient des séquences d’échappement et des séries de caractères ayant un but spécifique.

Les exemples de ce chapitre sont disponibles dans les sources sous le projet RegularExpressions...

Une première expression régulière

La chaîne Original est considérée comme étant la chaîne d’entrée. C’est sur celle-ci que les expressions régulières seront testées. Pour vérifier l’existence d’une série d’une chaîne dans celle-ci, il faudra exécuter les instructions suivantes :

string pattern = "vni"; 
MatchCollection matches = Regex.Matches(Original, 
                                       pattern, 
                                       RegexOptions.IgnoreCase); 
foreach (Match match in matches) 
{ 
    Console.WriteLine(match.Index); 
} 

Cet exemple définit un modèle, la chaîne de caractères vni. Ensuite, on fait appel à la méthode statique Matches de la classe Regex en passant comme arguments la chaîne originale et le schéma à retrouver, et en spécifiant l’option RegexOptions.IgnoreCase, permettant...

Les options de recherche

L’énumération RegexOptions est marquée avec l’attribut Flags. Cela signifie que ses valeurs peuvent être combinées avec des opérateurs de bits :

RegexOptions searchOptions = RegexOptions.IgnoreCase | 
                             RegexOptions.Multiline; 

La liste suivante présente les différentes valeurs de l’énumération RegexOptions :

  • None : spécifie qu’aucune option n’est définie. Si cette valeur est combinée avec une autre, elle sera ignorée.

  • IgnoreCase : spécifie que la casse est ignorée lors de la recherche.

  • Multiline : modifie la signification des caractères ˆ et $ de manière à ce qu’ils soient appliqués sur chaque ligne de la chaîne originale et non pas au début et à la fin de la chaîne entière.

  • ExplicitCapture : modifie la manière dont les résultats sont collectés en étant sûr que les captures valides sont celles qui sont explicitement nommées. 

  • Compiled : spécifie que l’expression régulière est compilée dans un assemblage. L’exécution est plus rapide, mais le temps de démarrage est augmenté....

Les caractères d’échappement

Les expressions régulières contiennent des caractères permettant de spécifier des parties de modèles. Ils doivent être précédés par un antislash \ de manière à être considérés comme un caractère réel. Par exemple, le caractère ? signifie que le caractère précédent peut apparaître zéro ou une fois. Pour faire une recherche sur le point d’interrogation lui-même, il faut le préfixer d’un antislash :

Console.WriteLine(Regex.Match(Original, @"jhu?")); 
Console.WriteLine(Regex.Match(Original, @"jhu\?")); 

Le résultat affiché est le suivant :

jhu_ 
jhu? 

Le résultat n’est pas identique suivant que le caractère ? est échappé ou non. Dans la première instruction, l’expression régulière recherche une suite de caractères pouvant être jh ou jhu alors que pour la seconde, la recherche porte sur la suite exacte jhu?.

Les méthodes statiques Escape et Unescape de la classe Regex permettent de transformer les caractères dans leur équivalent échappé :

Console.WriteLine(Regex.Escape(@"?"));        // \? 
Console.WriteLine(Regex.Unescape(@"\?"));    //...

Les ensembles

Les ensembles de caractères permettent de spécifier une série de caractères possible dans le modèle. Pour avoir une correspondance précise avec un ensemble de caractères, il faut les indiquer entre crochets :

Console.WriteLine(Regex.Match(Original, @"[Aa]hu"));    // ahu 

Le caractère ˆ positionné en premier après le crochet d’ouverture permet de spécifier l’inverse :

Console.WriteLine(Regex.Match(Original, @"[ˆAa]hu"));    // jhu 

Il est possible de spécifier une suite de caractères en séparant le premier du dernier par un tiret. Cela évite de devoir spécifier tous les caractères un par un :

Console.WriteLine(Regex.Match(Original, @"ah[n-z]"));    // ahu 

\d représente un chiffre. Son contraire est \D qui signifie tout caractère sauf un chiffre :

Console.WriteLine(Regex.Match(Original, @"\d\D\d"));    // 2-9 

\w est le diminutif de l’expression [a-zA-Z0-9_]. Il permet de rechercher tout caractère pouvant composer un mot :

Console.WriteLine(Regex.Match(Original, @"\w"));            // L 
Console.WriteLine(Regex.Match(Original, @"[a-zA-Z0-9_]"));  // L 

\s permet de spécifier un espace...

Les groupes

Il est parfois utile de pouvoir séparer une expression régulière en une série de plusieurs sous-expressions appelées des groupes. Pour former un groupe, l’expression doit être entourée de parenthèses :

Match result = Regex.Match(Original, @"(\d\d\d)-(\d\d\d)"); 
Console.WriteLine(result);                        // 022-999 
Console.WriteLine(result.Groups[0]);              // 022-999 
Console.WriteLine(result.Groups[1]);              // 022 
Console.WriteLine(result.Groups[2]);              // 999 

Dans cet exemple, vous pouvez remarquer que le résultat correspond au résultat complet de l’expression régulière tout comme le premier élément de la collection de groupes qui a l’index 0. Les groupes suivants sont ensuite formés par les groupes déterminés par les parenthèses dans leur ordre d’apparition dans l’expression régulière.

En plus de pouvoir séparer les résultats, les groupes peuvent également être...

Les ancres

Les caractères ˆ et $ permettent de spécifier une position particulière. Par défaut, ˆ correspond au début de la chaîne et $ correspond à la fin de celle-ci. Ainsi, pour faire une recherche sur le début de la chaîne, on utilisera une expression régulière de la forme suivante :

Console.WriteLine(Regex.Match(Original, @"ˆ\w"));        // L 

Suivant le contexte d’utilisation de ces caractères, ils ont une signification différente. ˆ peut être une ancre de début de chaîne ou un caractère de négation tandis que $ peut signifier la fin de la chaîne ou précéder un identifiant de groupe en cas de remplacement.

Si l’option RegexOptions.Multiline est spécifiée, ˆ correspondra au début de la chaîne ou de la ligne tandis que $ correspondra à la fin de la chaîne ou de la ligne.

Les quantifieurs

Les quantifieurs permettent de spécifier le nombre d’occurrences d’une correspondance. Le tableau suivant énumère les quantifieurs disponibles :

Quantifieur

Description

*

Zéro ou plusieurs correspondances.

+

Une ou plusieurs correspondances.

?

Zéro ou une correspondance.

{x}

Exactement x correspondances.

{x,}

Au moins x correspondances.

{x,y}

Entre x et y correspondances.

Un quantifieur s’applique au caractère ou groupe le précédant. Pour exemple, reprenons la précédente expression régulière : (\d\d\d)-(\d\d\d). Elle recherche deux séries de trois chiffres séparées par un tiret. Elle peut donc être convertie en (\d{3})-(\d{3}) :

Console.WriteLine(Regex.Match(Original, @"(\d{3})-(\d{3})")); 
// 022-999