Share via


Information om reguljärt uttrycksbeteende

Motorn för reguljära .NET-uttryck är en matchare för bakåtgående reguljära uttryck som innehåller en traditionell nondeterministisk Finite Automaton-motor (NFA), till exempel den som används av Perl, Python, Emacs och Tcl. Detta skiljer det från snabbare, men mer begränsade, rena reguljära uttryck Deterministiska Finite Automaton (DFA) motorer som de som finns i awk, egrep eller lex. Detta skiljer den också från standardiserade, men långsammare, POSIX-NFA:er. I följande avsnitt beskrivs de tre typerna av reguljära uttrycksmotorer och förklarar varför reguljära uttryck i .NET implementeras med hjälp av en traditionell NFA-motor.

Fördelar med NFA-motorn

När DFA-motorer utför mönstermatchning drivs deras bearbetningsordning av indatasträngen. Motorn börjar i början av indatasträngen och fortsätter sekventiellt för att avgöra om nästa tecken matchar mönstret för reguljära uttryck. De kan garantera att matcha den längsta möjliga strängen. Eftersom de aldrig testar samma tecken två gånger stöder DFA-motorer inte backtracking. Men eftersom en DFA-motor endast innehåller ändliga tillstånd kan den inte matcha ett mönster med backreferences, och eftersom den inte konstruerar en explicit expansion kan den inte avbilda underuttryck.

Till skillnad från DFA-motorer, när traditionella NFA-motorer utför mönstermatchning, drivs deras bearbetningsordning av mönster för reguljära uttryck. När den bearbetar ett visst språkelement använder motorn girig matchning. Det vill säga att den matchar så mycket av indatasträngen som möjligt. Men det sparar också sitt tillstånd efter att ha matchat en underuttryck. Om en matchning misslyckas kan motorn återgå till ett sparat tillstånd så att den kan prova ytterligare matchningar. Den här processen med att avbryta en lyckad underuttrycksmatchning så att senare språkelement i det reguljära uttrycket också kan matcha kallas backtracking. NFA-motorer använder backtracking för att testa alla möjliga expansioner av ett reguljärt uttryck i en specifik ordning och acceptera den första matchningen. Eftersom en traditionell NFA-motor konstruerar en specifik expansion av det reguljära uttrycket för en lyckad matchning, kan den samla in underuttrycksmatchningar och matchande backreferences. Men eftersom en traditionell NFA backar kan den besöka samma tillstånd flera gånger om den anländer till tillståndet över olika sökvägar. Därför kan den köras exponentiellt långsamt i värsta fall. Eftersom en traditionell NFA-motor accepterar den första matchningen den hittar kan den också lämna andra (eventuellt längre) matchningar oupptäckta.

POSIX NFA-motorer är som traditionella NFA-motorer, förutom att de fortsätter att backa tills de kan garantera att de har hittat den längsta matchningen som möjligt. Därför är en POSIX NFA-motor långsammare än en traditionell NFA-motor, och när du använder en POSIX NFA-motor kan du inte gynna en kortare matchning jämfört med en längre genom att ändra ordningen på bakåtspårningssökningen.

Traditionella NFA-motorer gynnas av programmerare eftersom de ger större kontroll över strängmatchning än antingen DFA- eller POSIX NFA-motorer. Även om de i värsta fall kan köras långsamt kan du styra dem för att hitta matchningar i linjär eller polynomtid genom att använda mönster som minskar tvetydigheterna och begränsar backtracking. Med andra ord, även om NFA-motorer handlar prestanda för kraft och flexibilitet, erbjuder de i de flesta fall bra till acceptabel prestanda om ett reguljärt uttryck är välskrivet och undviker fall där backtracking försämrar prestanda exponentiellt.

Kommentar

Information om prestandastraffet som orsakas av överdriven backning och sätt att skapa ett reguljärt uttryck för att arbeta runt dem finns i Backtracking.

.NET-motorfunktioner

För att dra nytta av fördelarna med en traditionell NFA-motor innehåller .NET-motorn för reguljära uttryck en komplett uppsättning konstruktioner som gör det möjligt för programmerare att styra backtrackingmotorn. Dessa konstruktioner kan användas för att hitta matchningar snabbare eller för att gynna specifika expansioner framför andra.

Andra funktioner i motorn för reguljära .NET-uttryck är följande:

  • Lata kvantifierare: ??, *?, +?, {n,m}?. Dessa konstruktioner instruerar backtracking-motorn att söka efter det minsta antalet upprepningar först. Däremot försöker vanliga giriga kvantifierare matcha det maximala antalet upprepningar först. I följande exempel visas skillnaden mellan de två. Ett reguljärt uttryck matchar en mening som slutar med ett tal, och en insamlingsgrupp är avsedd att extrahera talet. Det reguljära uttrycket .+(\d+)\. innehåller den giriga kvantifieraren .+, vilket gör att motorn för reguljära uttryck endast samlar in den sista siffran i talet. Det reguljära uttrycket .+?(\d+)\. innehåller däremot den lata kvantifieraren .+?, vilket gör att motorn för reguljära uttryck avbildar hela talet.

    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
    
    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
    

    De giriga och lata versionerna av det här reguljära uttrycket definieras enligt följande tabell:

    Mönster beskrivning
    .+ (girig kvantifierare) Matcha minst en förekomst av något tecken. Detta gör att motorn för reguljära uttryck matchar hela strängen och sedan backar efter behov för att matcha resten av mönstret.
    .+? (lat kvantifierare) Matcha minst en förekomst av ett tecken, men matcha så få som möjligt.
    (\d+) Matcha minst ett numeriskt tecken och tilldela det till den första insamlingsgruppen.
    \. Matcha en punkt.

    Mer information om lata kvantifierare finns i Kvantifierare.

  • Positiv lookahead: (?=underuttryck). Med den här funktionen kan backtracking-motorn återgå till samma plats i texten efter matchning av en underuttryck. Det är användbart för att söka i texten genom att verifiera flera mönster som börjar från samma position. Det gör också att motorn kan kontrollera att det finns en delsträng i slutet av matchningen utan att inkludera delsträngen i den matchade texten. I följande exempel används positiv lookahead för att extrahera orden i en mening som inte följs av skiljetecken.

    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
    
    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
    

    Det reguljära uttrycket \b[A-Z]+\b(?=\P{P}) definieras enligt följande tabell.

    Mönster beskrivning
    \b Starta matchningen vid en ordgräns.
    [A-Z]+ Matcha valfritt alfabetiskt tecken en eller flera gånger. Regex.Matches Eftersom metoden anropas med RegexOptions.IgnoreCase alternativet är jämförelsen skiftlägeskänslig.
    \b Avsluta matchningen vid en ordgräns.
    (?=\P{P}) Titta framåt för att avgöra om nästa tecken är en skiljeteckensymbol. Om det inte är det lyckas matchningen.

    Mer information om positiva lookahead-försäkran finns i Grupperingskonstruktioner.

  • Negativ lookahead: (?!underuttryck). Den här funktionen lägger till möjligheten att endast matcha ett uttryck om en underuttryck inte matchar. Detta är kraftfullt för att rensa en sökning, eftersom det ofta är enklare att ange ett uttryck för ett ärende som ska elimineras än ett uttryck för fall som måste inkluderas. Det är till exempel svårt att skriva ett uttryck för ord som inte börjar med "icke". I följande exempel används negativ lookahead för att undanta dem.

    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
    
    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
    

    Mönster för \b(?!non)\w+\b reguljära uttryck definieras enligt följande tabell.

    Mönster beskrivning
    \b Starta matchningen vid en ordgräns.
    (?!non) Se framåt för att se till att den aktuella strängen inte börjar med "icke". Om det gör det misslyckas matchningen.
    (\w+) Matcha ett eller flera ordtecken.
    \b Avsluta matchningen vid en ordgräns.

    Mer information om negativa lookahead-kontroller finns i Grupperingskonstruktioner.

  • Villkorsstyrd utvärdering: (?(uttrycket)ja|nej) och(?( namn)ja|nej), där uttrycket är en underuttryck som ska matchas, namnet är namnet på en samlande grupp, ja är strängen som matchar om uttrycket matchas eller om namnet är en giltig, icke-tom grupperad grupp och nej är den underuttryck som ska matcha om uttrycket inte matchas eller så är namnet inte en giltig, icke-tom grupperad grupp. Med den här funktionen kan motorn söka med fler än ett alternativt mönster, beroende på resultatet av en tidigare underuttrycksmatchning eller resultatet av en försäkran med noll bredd. Detta möjliggör en kraftfullare form av backreference som till exempel tillåter matchning av en underuttryck baserat på om en tidigare underuttryck matchades. Det reguljära uttrycket i följande exempel matchar stycken som är avsedda för både offentlig och intern användning. Stycken som endast är avsedda för internt bruk börjar med en <PRIVATE> tagg. Mönstret ^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$ för reguljära uttryck använder villkorsstyrd utvärdering för att tilldela innehållet i stycken som är avsedda för offentlig och för internt bruk för att separera insamlingsgrupper. Dessa stycken kan sedan hanteras på olika sätt.

    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.
    
    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.
    

    Mönster för reguljära uttryck definieras enligt följande tabell.

    Mönster beskrivning
    ^ Börja matchningen i början av en rad.
    (?<Pvt>\<PRIVATE\>\s)? Matcha noll eller en förekomst av strängen <PRIVATE> följt av ett blankstegstecken. Tilldela matchningen till en insamlingsgrupp med namnet Pvt.
    (?(Pvt)((\w+\p{P}?\s)+) Om insamlingsgruppen Pvt finns matchar du en eller flera förekomster av ett eller flera ordtecken följt av noll eller en skiljeteckenavgränsare följt av ett blankstegstecken. Tilldela delsträngen till den första insamlingsgruppen.
    |((\w+\p{P}?\s)+)) Om insamlingsgruppen Pvt inte finns matchar du en eller flera förekomster av ett eller flera ordtecken följt av noll eller en skiljeteckenavgränsare följt av ett blankstegstecken. Tilldela delsträngen till den tredje insamlingsgruppen.
    \r?$ Matcha slutet av en rad eller slutet av strängen.

    Mer information om villkorsstyrd utvärdering finns i Alternationskonstruktioner.

  • Balansera gruppdefinitioner: (?<name1-name2>subexpression). Med den här funktionen kan motorn för reguljära uttryck hålla reda på kapslade konstruktioner som parenteser eller inledande och avslutande hakparenteser. Ett exempel finns i Gruppera konstruktioner.

  • Atomiska grupper: (?>underuttryck). Med den här funktionen kan backtracking-motorn garantera att en underuttryck endast matchar den första matchningen som hittades för underuttrycket, som om uttrycket kördes oberoende av dess innehållande uttryck. Om du inte använder den här konstruktionen kan bakåtspårande sökningar från det större uttrycket ändra beteendet för en underuttryck. Det reguljära uttrycket (a+)\w matchar till exempel ett eller flera "a"-tecken, tillsammans med ett ordtecken som följer sekvensen med "a"-tecken, och tilldelar sekvensen med "a"-tecken till den första insamlingsgruppen. Men om det sista tecknet i indatasträngen också är ett "a" matchas det av \w språkelementet och ingår inte i den insamlade gruppen.

    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
    
    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
    

    Det reguljära uttrycket ((?>a+))\w förhindrar det här beteendet. Eftersom alla på varandra följande "a"-tecken matchas utan bakåtspårning innehåller den första insamlingsgruppen alla efterföljande "a"-tecken. Om "a"-tecknen inte följs av minst ett annat tecken än "a" misslyckas matchningen.

    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
    
    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
    

    Mer information om atomgrupper finns i Grupperingskonstruktioner.

  • Matchning från höger till vänster, som anges genom att RegexOptions.RightToLeft alternativet anges till en Regex klasskonstruktor eller matchningsmetod för statisk instans. Den här funktionen är användbar när du söker från höger till vänster i stället för från vänster till höger, eller i fall där det är mer effektivt att starta en matchning till höger i mönstret i stället för till vänster. Som följande exempel illustrerar kan användning av matchning från höger till vänster ändra beteendet för giriga kvantifierare. Exemplet utför två sökningar efter en mening som slutar med ett tal. Sökningen från vänster till höger som använder den giriga kvantifieraren + matchar en av de sex siffrorna i meningen, medan sökningen från höger till vänster matchar alla sex siffrorna. En beskrivning av mönster för reguljära uttryck finns i exemplet som illustrerar lata kvantifierare tidigare i det här avsnittet.

    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
    
    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
    

    Mer information om matchning från höger till vänster finns i Alternativ för reguljära uttryck.

  • Positiv och negativ lookbehind: (?<=subexpression) för positiv lookbehind och (?<!subexpression) för negativ lookbehind. Den här funktionen liknar lookahead, som beskrivs tidigare i det här avsnittet. Eftersom motorn för reguljära uttryck tillåter fullständig matchning från höger till vänster tillåter reguljära uttryck obegränsade lookbehinds. Positiva och negativa lookbehind kan också användas för att undvika kapslade kvantifierare när den kapslade underuttrycket är en supermängd av ett yttre uttryck. Reguljära uttryck med sådana kapslade kvantifierare ger ofta dåliga prestanda. I följande exempel verifieras till exempel att en sträng börjar och slutar med ett alfanumeriskt tecken, och att alla andra tecken i strängen är en av en större delmängd. Den utgör en del av det reguljära uttryck som används för att verifiera e-postadresser. Mer information finns i Så här kontrollerar du att strängar är i giltigt e-postformat.

    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
    
    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
    

    Det reguljära uttrycket ^[A-Z0-9]([-!#$%&'.*+/=?^`{}|~\w])*(?<=[A-Z0-9])$ definieras enligt följande tabell.

    Mönster beskrivning
    ^ Börja matchningen i början av strängen.
    [A-Z0-9] Matcha numeriska eller alfanumeriska tecken. (Jämförelsen är skiftlägeskänslig.)
    ([-!#$%&'.*+/=?^`{}|~\w])* Matcha noll eller fler förekomster av ordtecken, eller något av följande tecken: -, !, #, $, %, &, ', ., *, +, /, =, ?, ^, ', {, }, |eller ~.
    (?<=[A-Z0-9]) Titta bakom till föregående tecken, som måste vara numeriskt eller alfanumeriskt. (Jämförelsen är skiftlägeskänslig.)
    $ Avsluta matchningen i slutet av strängen.

    Mer information om positiva och negativa utseenden finns i Grupperingskonstruktioner.

Title Description
Backa Innehåller information om hur reguljära uttryck backar grenar för att hitta alternativa matchningar.
Kompilering och återanvändning Innehåller information om hur du kompilerar och återanvänder reguljära uttryck för att öka prestandan.
Tråd Valv ty Innehåller information om trådsäkerhet för reguljära uttryck och förklarar när du ska synkronisera åtkomsten till reguljära uttrycksobjekt.
Reguljära .NET-uttryck Ger en översikt över programmeringsspråkaspekten för reguljära uttryck.
Objektmodell för reguljärt uttryck Innehåller information och kodexempel som illustrerar hur du använder reguljära uttrycksklasser.
Språk för reguljärt uttryck – snabbreferens Innehåller information om den uppsättning tecken, operatorer och konstruktioner som du kan använda för att definiera reguljära uttryck.

Referens