Partager via


Comportement détaillé des expressions régulières

Le moteur de traitement des expressions régulières du .NET Framework est un outil de recherche qui fait appel aux expressions régulières en procédant par rétroaction. Cet outil intègre un moteur classique de type NFA (Nondeterministic Finite Automaton) similaire à celui utilisé par Perl, Python, Emacs et Tcl. C'est ce qui le différencie des moteurs de traitement des expressions régulières pures de type DFA (Deterministic Finite Automaton), plus rapides mais également plus limités, que l'on trouve dans awk, egrep ou lex. C'est également ce qui le différencie des moteurs NFA POSIX, standard, mais qui sont plus lents. La section suivante décrit les trois types de moteurs des expressions régulières et explique pourquoi les expressions régulières du .NET Framework sont implémentées à l'aide d'un moteur NFA classique.

Avantages du moteur NFA

Lorsque les moteurs DFA exécutent la correspondance de modèles, leur ordre de traitement est déterminé par la chaîne d'entrée. Le moteur commence au début de la chaîne d'entrée et continue de manière séquentielle pour déterminer si le caractère suivant correspond au modèle d'expression régulière. Ces moteurs peuvent garantir une correspondance avec la plus longue chaîne possible. Étant donné qu'ils ne testent jamais le même caractère deux fois, les moteurs DFA ne prennent pas en charge la rétroaction. Toutefois, comme un moteur DFA prend uniquement en compte un état fini, il ne peut pas rechercher un modèle avec références arrière, et comme il ne construit pas d'expansion explicite, il ne peut pas non plus capturer de sous-expressions.

Contrairement aux moteurs DFA, lorsque les moteurs NFA classiques effectuent une correspondance de modèles, leur ordre de traitement est déterminé par le modèle d'expression régulière. Lorsqu'il traite un élément de langage particulier, le moteur utilise une correspondance gourmande ; autrement dit, il recherche le maximum de la chaîne d'entrée possible. Mais il enregistre également son état après trouvé la correspondance d'une sous-expression. Si une correspondance finit par échouer, le moteur peut retourner à un état enregistré pour tenter d'autres correspondances. Ce processus consistant à abandonner une correspondance réussie de sous-expression pour que les éléments de langage suivants dans l'expression régulière puissent également correspondre est appelé rétroaction. Les moteurs NFA utilisent la rétroaction pour tester toutes les expansions possibles d'une expression régulière dans un ordre spécifique et accepter la première correspondance. Comme un moteur NFA classique procède à une expansion spécifique des expressions régulières pour obtenir une correspondance, il peut capturer des occurrences de sous-expressions et de références arrière. Cependant, étant donné qu'un moteur NFA classique recherche par rétroaction, il peut visiter exactement le même état plusieurs fois si l'état est accessible via différents chemins. Son exécution risque ainsi de se ralentir considérablement. Comme un moteur NFA classique accepte la première correspondance trouvée, il peut également en négliger d'autres (éventuellement plus longues).

Les moteurs NFA POSIX sont similaires aux moteurs NFA classiques, à la différence qu'ils continuent de rechercher rétroactivement jusqu'à ce qu'ils aient trouvé de façon certaine la correspondance la plus longue possible. C'est la raison pour laquelle un moteur NFA POSIX est plus lent qu'un moteur NFA classique et, si vous utilisez un moteur NFA POSIX, il est impossible de préférer la correspondance la plus courte en changeant l'ordre de la recherche rétroactive.

Les moteurs NFA classiques ont la préférence des programmeurs parce qu'ils permettent de mieux contrôler la recherche de chaînes que les moteurs DFA ou NFA POSIX. Même si leur exécution est parfois très lente, il reste possible de les amener à effectuer des recherches en mode linéaire ou polynomial à l'aide de modèles propres à limiter les ambiguïtés et à réduire la rétroaction. En d'autres termes, bien que les moteurs NFA privilégient les performances au détriment de la rapidité et de la flexibilité, ils offrent souvent des performances acceptables si une expression régulière est correctement écrite et évite des casses susceptibles de nuire exponentiellement à l'efficacité de la rétroaction.

RemarqueRemarque

Pour plus d'informations sur les pertes en termes de performances entraînées par une rétroaction excessive et les moyens de créer des expressions régulières pour les contourner, consultez Rétroaction.

Possibilités du moteur du .NET Framework

Le moteur de traitement des expressions régulières du .NET Framework propose un ensemble complet de constructions pour permettre aux programmeurs de diriger le moteur de recherche rétroactive et de tirer parti d'un moteur NFA classique. Ces constructions peuvent servir à rechercher des correspondances plus rapidement ou à indiquer la priorité d'expansions spécifiques par rapport à d'autres.

Le moteur de traitement des expressions régulières du .NET Framework inclut également les fonctionnalités suivantes :

  • Quantificateurs paresseux (parfois dits « tardifs ») : ??, *?, +?, {n,m}?. Ces constructions indiquent au moteur de recherche rétroactive de rechercher d'abord le nombre minimal de répétitions. Par opposition, les quantificateurs gourmands ordinaires essaient de trouver d'abord le nombre maximal de répétitions. L'exemple suivant illustre la différence entre les deux. Une expression régulière correspond à une phrase se terminant par un nombre, qu'un groupe de capture permet d'extraire. L'expression régulière .+(\d+)\. inclut le quantificateur gourmand .+, qui indique au moteur des expressions régulières de capturer uniquement le dernier chiffre du nombre. Par opposition, l'expression régulière .+?(\d+)\. inclut le quantificateur paresseux .+?, qui indique au moteur des expressions régulières de capturer le nombre entier.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim greedyPattern As String = ".+(\d+)\."
          Dim lazyPattern As String = ".+?(\d+)\."
          Dim input As String = "This sentence ends with the number 107325."
          Dim match As Match
    
          ' Match using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (greedy): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", greedyPattern)
          End If
    
          ' Match using lazy quantifier .+?.
          match = Regex.Match(input, lazyPattern)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (lazy): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", lazyPattern)
          End If
       End Sub
    End Module
    ' The example displays the following output:
    '       Number at end of sentence (greedy): 5
    '       Number at end of sentence (lazy): 107325
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string greedyPattern = @".+(\d+)\.";
          string lazyPattern = @".+?(\d+)\.";
          string input = "This sentence ends with the number 107325.";
          Match match;
    
          // Match using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (greedy): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", greedyPattern);
    
          // Match using lazy quantifier .+?.
          match = Regex.Match(input, lazyPattern);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (lazy): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", lazyPattern);
       }
    }
    // The example displays the following output:
    //       Number at end of sentence (greedy): 5
    //       Number at end of sentence (lazy): 107325
    

    Les versions gourmande et paresseuse de cette expression régulière sont définies comme indiqué dans le tableau suivant.

    Modèle

    Description

    .+ (quantificateur gourmand)

    Établit une correspondance avec au moins une occurrence d'un caractère. Le moteur des expressions régulières établit ainsi une correspondance avec la chaîne entière, puis effectue autant de recherches rétroactives que nécessaires pour trouver le reste du modèle.

    .+? (quantificateur paresseux)

    Établit une correspondance avec au moins une occurrence d'un caractère, mais recherche le minimum de correspondances possibles.

    (\d+)

    Établit une correspondance avec au moins un chiffre et l'attribue au premier groupe de capture.

    \.

    Établit une correspondance avec un point.

    Pour plus d'informations sur les quantificateurs paresseux, consultez Quantificateurs.

  • Préanalyse positive : (?=sous-expression). Cette fonctionnalité permet au moteur de recherche rétroactive de retourner au même endroit dans le texte après avoir trouvé la correspondance d'une sous-expression. Elle est utile pour effectuer une recherche dans le texte en vérifiant plusieurs modèles à partir d'une même position. Elle permet également au moteur de vérifier qu'une sous-chaîne existe à la fin de la correspondance sans inclure la sous-chaîne dans le texte trouvé. L'exemple suivant utilise la préanalyse positive pour extraire les mots d'une phrase qui ne sont pas suivis de symboles de ponctuation.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim pattern As String = "\b[A-Z]+\b(?=\P{P})"
          Dim input As String = "If so, what comes next?"
          For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
             Console.WriteLine(match.Value)
          Next   
       End Sub
    End Module
    ' The example displays the following output:
    '       If
    '       what
    '       comes
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string pattern = @"\b[A-Z]+\b(?=\P{P})";
          string input = "If so, what comes next?";
          foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
             Console.WriteLine(match.Value);
       }
    }
    // The example displays the following output:
    //       If
    //       what
    //       comes
    

    L'expression régulière \b[A-Z]+\b(?=\P{P}) est définie comme indiqué dans le tableau suivant.

    Modèle

    Description

    \b

    Commence la correspondance à la limite d'un mot.

    [A-Z]+

    Établit une ou plusieurs fois la correspondance avec un caractère alphabétique. Étant donné que la méthode Regex.Matches est appelée avec l'option RegexOptions.IgnoreCase, la comparaison n'est pas sensible à la casse.

    \b

    Termine la correspondance à la limite d'un mot.

    (?=\P{P})

    Effectue une préanalyse pour déterminer si le caractère suivant est un symbole de ponctuation. Si ce n'est pas le cas, la correspondance réussit.

    Pour plus d'informations sur les assertions de préanalyse positive, consultez Constructions de regroupement.

  • Préanalyse négative : (?!sous-expression). Cette fonctionnalité ajoute la possibilité de retrouver une expression uniquement si une sous-expression n'a pas de correspondance. Elle est particulièrement efficace pour affiner une recherche, étant donné qu'une expression correspondant à un cas à éliminer est souvent beaucoup plus simple qu'une expression correspondant à des cas à inclure. Par exemple, il est difficile d'écrire une expression pour les mots ne commençant pas par « non ». L'exemple suivant utilise la préanalyse négative pour les exclure.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim pattern As String = "\b(?!non)\w+\b"
          Dim input As String = "Nonsense is not always non-functional."
          For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
             Console.WriteLine(match.Value)
          Next
       End Sub
    End Module
    ' The example displays the following output:
    '       is
    '       not
    '       always
    '       functional
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string pattern = @"\b(?!non)\w+\b";
          string input = "Nonsense is not always non-functional.";
          foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
             Console.WriteLine(match.Value);
       }
    }
    // The example displays the following output:
    //       is
    //       not
    //       always
    //       functional
    

    Le modèle d'expression régulière \b(?!non)\w+\b est défini comme indiqué dans le tableau suivant.

    Modèle

    Description

    \b

    Commence la correspondance à la limite d'un mot.

    (?! non)

    Effectue une préanalyse pour vérifier que la chaîne actuelle ne commence pas par « non ». Le cas échéant, la correspondance échoue.

    (\w+)

    Établit une correspondance avec un ou plusieurs caractères alphabétiques.

    \b

    Termine la correspondance à la limite d'un mot.

    Pour plus d'informations sur les assertions de préanalyse négative, consultez Constructions de regroupement.

  • Évaluation conditionnelle : (?(expression)oui|non) et (?(nom)oui|non), où expression est une sous-expression à rechercher, nom est le nom d'un groupe de capture, oui est la chaîne à rechercher si une correspondance est établie pour expression ou si nom est un groupe capturé valide et non vide, et non est la sous-expression à rechercher si aucune correspondance n'est établie pour expression ou si nom n'est pas un groupe capturé valide et non vide. Cette fonctionnalité permet au moteur d'effectuer une recherche à l'aide de plusieurs autres modèles, selon le résultat d'une correspondance de sous-expression précédente ou le résultat d'une assertion de largeur nulle. Par exemple, un formulaire de référence arrière plus puissant peut ainsi rechercher une sous-expression selon qu'une sous-expression précédente a été trouvée ou non. L'expression régulière de l'exemple suivant établit une correspondance avec des paragraphes destinés à un usage public et interne. Les paragraphes prévus uniquement pour un usage interne commencent par une balise <PRIVATE>. Le modèle d'expression régulière ^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$ utilise une évaluation conditionnelle pour assigner le contenu des paragraphes destinés à un usage public et interne à des groupes de capture différents. Ces paragraphes peuvent ensuite être gérés séparément.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim input As String = "<PRIVATE> This is not for public consumption." + vbCrLf + _
                                "But this is for public consumption." + vbCrLf + _
                                "<PRIVATE> Again, this is confidential." + vbCrLf
          Dim pattern As String = "^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$"
          Dim publicDocument As String = Nothing
          Dim privateDocument As String = Nothing
    
          For Each match As Match In Regex.Matches(input, pattern, RegexOptions.Multiline)
             If match.Groups(1).Success Then
                privateDocument += match.Groups(1).Value + vbCrLf
             Else
                publicDocument += match.Groups(3).Value + vbCrLf   
                privateDocument += match.Groups(3).Value + vbCrLf
             End If  
          Next
    
          Console.WriteLine("Private Document:")
          Console.WriteLine(privateDocument)
          Console.WriteLine("Public Document:")
          Console.WriteLine(publicDocument)
       End Sub
    End Module
    ' The example displays the following output:
    '    Private Document:
    '    This is not for public consumption.
    '    But this is for public consumption.
    '    Again, this is confidential.
    '    
    '    Public Document:
    '    But this is for public consumption.
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string input = "<PRIVATE> This is not for public consumption." + Environment.NewLine + 
                         "But this is for public consumption." + Environment.NewLine + 
                         "<PRIVATE> Again, this is confidential.\n";  
          string pattern = @"^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$";
          string publicDocument = null, privateDocument = null;
    
          foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
          {
             if (match.Groups[1].Success) {
                privateDocument += match.Groups[1].Value + "\n";
             }
             else {
                publicDocument += match.Groups[3].Value + "\n";   
                privateDocument += match.Groups[3].Value + "\n";
             }  
          }
    
          Console.WriteLine("Private Document:");
          Console.WriteLine(privateDocument);
          Console.WriteLine("Public Document:");
          Console.WriteLine(publicDocument);
       }
    }
    // The example displays the following output:
    //    Private Document:
    //    This is not for public consumption.
    //    But this is for public consumption.
    //    Again, this is confidential.
    //    
    //    Public Document:
    //    But this is for public consumption.
    

    Le modèle d'expression régulière est défini comme indiqué dans le tableau suivant.

    Modèle

    Description

    ^

    Commence la correspondance au début d'une ligne.

    (?<Pvt>\<PRIVATE\>\s)?

    Établit une correspondance avec zéro, une ou plusieurs occurrences de la chaîne <PRIVATE>, suivie d'un espace. Assigne la correspondance à un groupe de capture nommé Pvt.

    (?(Pvt)((\w+\p{P}? \s)+)

    Si le groupe de capture Pvt existe, établit la correspondance avec une ou plusieurs occurrences d'un ou plusieurs caractères alphabétiques suivis de zéro ou un séparateur de ponctuation suivi d'un espace. Assigne la sous-chaîne au premier groupe de capture.

    |((\w+\p{P}? \s)+))

    Si le groupe de capture Pvt n'existe pas, établit la correspondance avec une ou plusieurs occurrences d'un ou plusieurs caractères alphabétiques suivis de zéro ou un séparateur de ponctuation suivi d'un espace. Assigne la sous-chaîne au troisième groupe de capture.

    \r?$

    Établit une correspondance avec la fin d'une ligne ou d'une chaîne.

    Pour plus d'informations sur l'évaluation conditionnelle, consultez Constructions d'alternative.

  • Équilibres de définition de groupe : (?<nom1-nom2> sous-expression). Cette fonctionnalité permet au moteur des expressions régulières suivre des constructions imbriquées, telles que des parenthèses ou des crochets ouvrants et fermants. Pour obtenir un exemple, consultez Constructions de regroupement.

  • Sous-expressions de recherche non rétroactive (également appelées sous-expressions gourmandes) :(?>sous-expression). Cette fonctionnalité permet au moteur de recherche non rétroactive de vérifier qu'une sous-expression correspond uniquement à la première occurrence trouvée pour cette sous-expression, comme si l'expression s'exécutait indépendamment de l'expression qui la contient. Sans cette construction, les recherches rétroactives à partir de la plus longue expression peuvent modifier le comportement d'une sous-expression. Par exemple, l'expression régulière (a+)\w correspond à un ou plusieurs caractères« a », ainsi qu'à un caractère alphabétique suivant la séquence de caractères « a », et assigne la séquence de caractères « a » au premier groupe de capture. Toutefois, si le dernier caractère de la chaîne d'entrée est également un « a », il est associé à l'élément de langage \w et n'est pas inclus dans le groupe capturé.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim inputs() As String = { "aaaaa", "aaaaab" }
          Dim backtrackingPattern As String = "(a+)\w"
          Dim match As Match
    
          For Each input As String In inputs
             Console.WriteLine("Input: {0}", input)
             match = Regex.Match(input, backtrackingPattern)
             Console.WriteLine("   Pattern: {0}", backtrackingPattern)
             If match.Success Then 
                Console.WriteLine("      Match: {0}", match.Value)
                Console.WriteLine("      Group 1: {0}", match.Groups(1).Value)
             Else 
                Console.WriteLine("      Match failed.")
             End If   
          Next
          Console.WriteLine()            
       End Sub
    End Module
    ' The example displays the following output:
    '       Input: aaaaa
    '          Pattern: (a+)\w
    '             Match: aaaaa
    '             Group 1: aaaa
    '       Input: aaaaab
    '          Pattern: (a+)\w
    '             Match: aaaaab
    '             Group 1: aaaaa
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string[] inputs = { "aaaaa", "aaaaab" };
          string backtrackingPattern = @"(a+)\w";
          Match match;
    
          foreach (string input in inputs) {
             Console.WriteLine("Input: {0}", input);
             match = Regex.Match(input, backtrackingPattern);
             Console.WriteLine("   Pattern: {0}", backtrackingPattern);
             if (match.Success) { 
                Console.WriteLine("      Match: {0}", match.Value);
                Console.WriteLine("      Group 1: {0}", match.Groups[1].Value);
             }
             else {
                Console.WriteLine("      Match failed.");
             }   
          }
          Console.WriteLine();            
       }
    }
    // The example displays the following output:
    //       Input: aaaaa
    //          Pattern: (a+)\w
    //             Match: aaaaa
    //             Group 1: aaaa
    //       Input: aaaaab
    //          Pattern: (a+)\w
    //             Match: aaaaab
    //             Group 1: aaaaa
    

    L'expression régulière ((?>a+))\w empêche ce comportement. Étant donné que tous les caractères « a » consécutifs sont trouvés sans rétroaction, le premier groupe de capture inclut tous les caractères « a » consécutifs. Si les caractères « a » ne sont pas suivis d'au moins un caractère supplémentaire autre que « a », la correspondance échoue.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim inputs() As String = { "aaaaa", "aaaaab" }
          Dim nonbacktrackingPattern As String = "((?>a+))\w"
          Dim match As Match
    
          For Each input As String In inputs
             Console.WriteLine("Input: {0}", input)
             match = Regex.Match(input, nonbacktrackingPattern)
             Console.WriteLine("   Pattern: {0}", nonbacktrackingPattern)
             If match.Success Then 
                Console.WriteLine("      Match: {0}", match.Value)
                Console.WriteLine("      Group 1: {0}", match.Groups(1).Value)
             Else 
                Console.WriteLine("      Match failed.")
             End If   
          Next
          Console.WriteLine()            
       End Sub
    End Module
    ' The example displays the following output:
    '       Input: aaaaa
    '          Pattern: ((?>a+))\w
    '             Match failed.
    '       Input: aaaaab
    '          Pattern: ((?>a+))\w
    '             Match: aaaaab
    '             Group 1: aaaaa
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string[] inputs = { "aaaaa", "aaaaab" };
          string nonbacktrackingPattern = @"((?>a+))\w";
          Match match;
    
          foreach (string input in inputs) {
             Console.WriteLine("Input: {0}", input);
             match = Regex.Match(input, nonbacktrackingPattern);
             Console.WriteLine("   Pattern: {0}", nonbacktrackingPattern);
             if (match.Success) { 
                Console.WriteLine("      Match: {0}", match.Value);
                Console.WriteLine("      Group 1: {0}", match.Groups[1].Value);
             }
             else {
                Console.WriteLine("      Match failed.");
             }   
          }
          Console.WriteLine();            
       }
    }
    // The example displays the following output:
    //       Input: aaaaa
    //          Pattern: ((?>a+))\w
    //             Match failed.
    //       Input: aaaaab
    //          Pattern: ((?>a+))\w
    //             Match: aaaaab
    //             Group 1: aaaaa
    

    Pour plus d'informations sur les sous-expressions de recherche non rétroactive, consultez Constructions de regroupement.

  • Recherche de correspondances de droite à gauche (spécifiée en attribuant l'option RegexOptions.RightToLeft à un constructeur de classe Regex ou à une méthode de correspondance d'instance statique. Cette fonctionnalité est utile lorsque la recherche s'effectue de droite à gauche et non de gauche à droite ou dans les cas où il est plus efficace de lancer une recherche en commençant par la partie droite du modèle qu'en commençant par la gauche. Comme l'illustre l'exemple suivant, l'utilisation de la recherche de correspondances de droite à gauche peut modifier le comportement des quantificateurs gourmands. L'exemple effectue deux recherches pour une phrase qui se termine par un nombre. La recherche de gauche à droite qui utilise le quantificateur gourmand + trouve l'un des six chiffres dans la phrase, alors que la recherche de droite à gauche trouve l'ensemble des six chiffres. Pour une description du modèle d'expression régulière, consultez l'exemple qui illustre les quantificateurs paresseux plus loin dans cette section.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim greedyPattern As String = ".+(\d+)\."
          Dim input As String = "This sentence ends with the number 107325."
          Dim match As Match
    
          ' Match from left-to-right using lazy quantifier .+?.
          match = Regex.Match(input, greedyPattern)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (left-to-right): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", greedyPattern)
          End If
    
          ' Match from right-to-left using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern, RegexOptions.RightToLeft)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (right-to-left): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", greedyPattern)
          End If
       End Sub
    End Module
    ' The example displays the following output:
    '       Number at end of sentence (left-to-right): 5
    '       Number at end of sentence (right-to-left): 107325
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string greedyPattern = @".+(\d+)\.";
          string input = "This sentence ends with the number 107325.";
          Match match;
    
          // Match from left-to-right using lazy quantifier .+?.
          match = Regex.Match(input, greedyPattern);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (left-to-right): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", greedyPattern);
    
          // Match from right-to-left using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern, RegexOptions.RightToLeft);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (right-to-left): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", greedyPattern);
       }
    }
    // The example displays the following output:
    //       Number at end of sentence (left-to-right): 5
    //       Number at end of sentence (right-to-left): 107325
    

    Pour plus d'informations sur la recherche de correspondances de droite à gauche, consultez Options des expressions régulières.

  • Postanalyse positive et négative : (?<=sous-expression) pour une postanalyse positive et (?<!sous-expression) pour une postanalyse négative. Cette fonctionnalité est semblable à la préanalyse décrite précédemment dans cette rubrique. Comme le moteur des expressions régulières permet une recherche complète des correspondances de droite à gauche, les expressions régulières autorisent des postanalyses illimitées. La postanalyse positive et négative peut également être utilisée pour éviter d'imbriquer des quantificateurs lorsque la sous-expression imbriquée est un sur-ensemble d'une expression externe. Les expressions régulières comportant ces quantificateurs imbriqués offrent souvent des performances médiocres. L'exemple suivant vérifie qu'une chaîne commence et se termine par un caractère alphanumérique, et que tous les autres caractères de la chaîne sont compris dans un plus grand sous-ensemble. Il forme une partie de l'expression régulière utilisée pour valider des adresses de messagerie ; pour plus d'informations, consultez Comment : vérifier que des chaînes sont dans un format d'adresse de messagerie valide.

    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim inputs() As String = { "jack.sprat", "dog#", "dog#1", "me.myself", 
                                     "me.myself!" }
          Dim pattern As String = "^[A-Z0-9]([-!#$%&'.*+/=?^`{}|~\w])*(?<=[A-Z0-9])$"
          For Each input As String In inputs
             If Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase) Then
                Console.WriteLine("{0}: Valid", input)
             Else
                Console.WriteLine("{0}: Invalid", input)
             End If   
          Next
       End Sub
    End Module
    ' The example displays the following output:
    '       jack.sprat: Valid
    '       dog#: Invalid
    '       dog#1: Valid
    '       me.myself: Valid
    '       me.myself!: Invalid
    
    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string[] inputs = { "jack.sprat", "dog#", "dog#1", "me.myself", 
                              "me.myself!" };
          string pattern = @"^[A-Z0-9]([-!#$%&'.*+/=?^`{}|~\w])*(?<=[A-Z0-9])$";
          foreach (string input in inputs) {
             if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
                Console.WriteLine("{0}: Valid", input);
             else
                Console.WriteLine("{0}: Invalid", input);
          }
       }
    }
    // The example displays the following output:
    //       jack.sprat: Valid
    //       dog#: Invalid
    //       dog#1: Valid
    //       me.myself: Valid
    //       me.myself!: Invalid
    

    L'expression régulière ^[A-Z0-9]([-!#$%&'.*+/=?^`{}|~\w])*(?<=[A-Z0-9])$ est définie comme indiqué dans le tableau suivant.

    Modèle

    Description

    ^

    Commence la correspondance au début de la chaîne.

    [A-Z0-9]

    Établit une correspondance avec n'importe quel caractère numérique ou alphanumérique. (La comparaison ne respecte pas la casse.)

    ([-!#$%&'.*+/=?^`{}|~\w])*

    Établit une correspondance avec zéro, une ou plusieurs occurrences d'un caractère alphabétique ou de l'un des caractères suivants : -, !, #, $, %, &, ', ., *, +, /, =, ?, ^, `, {, }, |, or ~.

    (?<=[A-Z0-9])

    Effectue une postanalyse du caractère précédent, qui doit être numérique ou alphanumérique. (La comparaison ne respecte pas la casse.)

    $

    Termine la correspondance à la fin de la chaîne.

    Pour plus d'informations sur la postanalyse positive et négative, consultez Constructions de regroupement.

Rubriques connexes

Titre

Description

Rétroaction

Fournit des informations sur la manière dont la rétroaction des expressions régulières crée des branches pour trouver d'autres correspondances.

Compilation et réutilisation

Fournit des informations sur la compilation et la réutilisation des expressions régulières pour augmenter les performances.

Sécurité des threads

Fournit des informations sur la sécurité des threads des expressions régulières et explique quand vous devez synchroniser l'accès à des objets d'expressions régulières.

Expressions régulières du .NET Framework

Présente une vue d'ensemble du langage de programmation des expressions régulières.

Modèle objet d'expression régulière

Fournit des informations et des exemples de code montrant comment utiliser les classes d'expressions régulières.

Exemples d'expressions régulières

Contient des exemples de code qui illustrent l'utilisation d'expressions régulières dans des applications courantes.

Éléments du langage des expressions régulières

Fournit des informations sur l'ensemble des caractères, opérateurs et constructions que vous pouvez utiliser pour définir des expressions régulières.

Référence

System.Text.RegularExpressions