Dela via


Alternativ för reguljära uttryck

Som standard är jämförelsen av en indatasträng med eventuella literaltecken i ett reguljärt uttrycksmönster skiftlägeskänsligt, blanksteg i ett reguljärt uttrycksmönster tolkas som literala blankstegstecken, och att samla in grupper i ett reguljärt uttryck namnges implicit såväl som explicit. Du kan ändra dessa och flera andra aspekter av standardbeteendet för reguljära uttryck genom att ange alternativ för reguljära uttryck. Några av de här alternativen, som visas i följande tabell, kan inkluderas infogade som en del av mönstret för reguljära uttryck, eller så kan de levereras till en System.Text.RegularExpressions.Regex klasskonstruktor eller statisk mönstermatchningsmetod som ett System.Text.RegularExpressions.RegexOptions uppräkningsvärde.

RegexOptions medlem Infogat tecken Effekt Mer information
None Inte tillgängliga Använd standardbeteende. Standardalternativ
IgnoreCase i Använd skiftlägesokänslig matchning. Skiftlägesokänslig matchning
Multiline m Använd flerradsläge, där ^ och $ anger början och slutet på varje rad (i stället för början och slutet av indatasträngen). Flerradsläge
Singleline s Använd enradsläge, där perioden (.) matchar varje tecken (i stället för alla tecken utom \n). Enkelradsläge
ExplicitCapture n Samla inte in icke namngivna grupper. De enda giltiga avbildningarna namnges uttryckligen eller numrerade grupper i formulärnamnets (?<>underuttryck.) Endast explicita avbildningar
Compiled Inte tillgängliga Kompilera det reguljära uttrycket till en sammansättning. Kompilerade reguljära uttryck
IgnorePatternWhitespace x Exkludera blanksteg som inte är inkapslade från mönstret och aktivera kommentarer efter ett taltecken (#). Ignorera tomt utrymme
RightToLeft Inte tillgängliga Ändra sökriktningen. Sökningen flyttas från höger till vänster i stället för från vänster till höger. Höger-till-vänster-läge
ECMAScript Inte tillgängliga Aktivera ECMAScript-kompatibelt beteende för uttrycket. ECMAScript-matchningsbeteende
CultureInvariant Inte tillgängliga Ignorera kulturella skillnader i språk. Jämförelse med den invarianta kulturen
NonBacktracking Inte tillgängliga Matcha med en metod som undviker backtracking och garanterar linjär tidsbearbetning i längden på indata. (Finns i .NET 7 och senare versioner.) Icke-bakåtspårningsläge

Ange alternativ

Du kan ange alternativ för reguljära uttryck på något av tre sätt:

  • I parametern options för en System.Text.RegularExpressions.Regex klasskonstruktor eller statisk (Shared i Visual Basic) mönstermatchningsmetod, till exempel Regex(String, RegexOptions) eller Regex.Match(String, String, RegexOptions). Parametern options är en bitvis ELLER kombination av System.Text.RegularExpressions.RegexOptions uppräknade värden.

    När alternativ anges till en Regex instans med hjälp av parametern options för en klasskonstruktor tilldelas alternativen till System.Text.RegularExpressions.RegexOptions egenskapen. Egenskapen återspeglar dock System.Text.RegularExpressions.RegexOptions inte infogade alternativ i själva mönstret för reguljära uttryck.

    I följande exempel visas en bild. Den använder parametern options för Regex.Match(String, String, RegexOptions) metoden för att aktivera skiftlägesokänslig matchning och för att ignorera mönstrets blanksteg när du identifierar ord som börjar med bokstaven "d".

    string pattern = @"d \w+ \s";
    string input = "Dogs are decidedly good pets.";
    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace;
    
    foreach (Match match in Regex.Matches(input, pattern, options))
        Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
    // The example displays the following output:
    //    'Dogs // found at index 0.
    //    'decidedly // found at index 9.
    
    Dim pattern As String = "d \w+ \s"
    Dim input As String = "Dogs are decidedly good pets."
    Dim options As RegexOptions = RegexOptions.IgnoreCase Or RegexOptions.IgnorePatternWhitespace
    
    For Each match As Match In Regex.Matches(input, pattern, options)
        Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
    Next
    ' The example displays the following output:
    '    'Dogs ' found at index 0.
    '    'decidedly ' found at index 9.      
    
  • Genom att använda infogade alternativ i ett reguljärt uttrycksmönster med syntaxen (?imnsx-imnsx). Alternativet gäller för mönstret från den punkt där alternativet definieras för antingen slutet av mönstret eller på den punkt där alternativet är odefinierat av ett annat infogat alternativ. Observera att egenskapen för System.Text.RegularExpressions.RegexOptions en Regex instans inte återspeglar dessa infogade alternativ. Mer information finns i avsnittet Om diverse konstruktioner .

    I följande exempel visas en bild. Den använder infogade alternativ för att aktivera skiftlägesokänslig matchning och för att ignorera mönstrets blanksteg när du identifierar ord som börjar med bokstaven "d".

    string pattern = @"(?ix) d \w+ \s";
    string input = "Dogs are decidedly good pets.";
    
    foreach (Match match in Regex.Matches(input, pattern))
        Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
    // The example displays the following output:
    //    'Dogs // found at index 0.
    //    'decidedly // found at index 9.
    
    Dim pattern As String = "\b(?ix) d \w+ \s"
    Dim input As String = "Dogs are decidedly good pets."
    
    For Each match As Match In Regex.Matches(input, pattern)
        Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
    Next
    ' The example displays the following output:
    '    'Dogs ' found at index 0.
    '    'decidedly ' found at index 9.      
    
  • Genom att tillämpa infogade alternativ i en viss grupperingskonstruktion i ett mönster för reguljära uttryck med syntaxunderuttryck(?imnsx-imnsx:). Inget tecken innan en uppsättning alternativ aktiverar inställningen. ett minustecken innan en uppsättning alternativ inaktiverar inställningen. (? är en fast del av språkkonstruktionens syntax som krävs oavsett om alternativen är aktiverade eller inaktiverade.) Alternativet gäller endast för den gruppen. Mer information finns i Grupperingskonstruktioner.

    I följande exempel visas en bild. Den använder infogade alternativ i en grupperingskonstruktion för att aktivera skiftlägesokänslig matchning och ignorera mönstervitt utrymme när du identifierar ord som börjar med bokstaven "d".

    string pattern = @"\b(?ix: d \w+)\s";
    string input = "Dogs are decidedly good pets.";
    
    foreach (Match match in Regex.Matches(input, pattern))
        Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
    // The example displays the following output:
    //    'Dogs // found at index 0.
    //    'decidedly // found at index 9.
    
    Dim pattern As String = "\b(?ix: d \w+)\s"
    Dim input As String = "Dogs are decidedly good pets."
    
    For Each match As Match In Regex.Matches(input, pattern)
        Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
    Next
    ' The example displays the following output:
    '    'Dogs ' found at index 0.
    '    'decidedly ' found at index 9.      
    

Om alternativ anges infogade inaktiverar ett minustecken (-) innan ett alternativ eller en uppsättning alternativ dessa alternativ inaktiveras. Till exempel aktiverar den infogade konstruktionen (?ix-ms) RegexOptions.IgnoreCase alternativen och RegexOptions.IgnorePatternWhitespace och inaktiverar RegexOptions.Multiline alternativen och RegexOptions.Singleline . Alla alternativ för reguljära uttryck är inaktiverade som standard.

Kommentar

Om alternativen för reguljära uttryck som anges i parametern options för en konstruktor eller metodanrop står i konflikt med de alternativ som anges infogade i ett reguljärt uttrycksmönster, används de infogade alternativen.

Följande fem alternativ för reguljära uttryck kan anges både med parametern alternativ och infogade:

Följande fem alternativ för reguljära uttryck kan anges med hjälp av parametern options men kan inte anges infogade:

Fastställa alternativ

Du kan avgöra vilka alternativ som angavs för ett Regex objekt när det instansierades genom att hämta värdet för den skrivskyddade Regex.Options egenskapen.

Om du vill testa om det finns något annat alternativ än RegexOptions.Noneutför du en AND-åtgärd med värdet för egenskapen och det RegexOptions värde som du är intresserad avRegex.Options. Testa sedan om resultatet är lika med det RegexOptions värdet. I följande exempel testas om alternativet RegexOptions.IgnoreCase har angetts.

if ((rgx.Options & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase)
    Console.WriteLine("Case-insensitive pattern comparison.");
else
    Console.WriteLine("Case-sensitive pattern comparison.");
If (rgx.Options And RegexOptions.IgnoreCase) = RegexOptions.IgnoreCase Then
    Console.WriteLine("Case-insensitive pattern comparison.")
Else
    Console.WriteLine("Case-sensitive pattern comparison.")
End If

Om du vill testa för avgör du om värdet för RegexOptions.NoneRegex.Options egenskapen är lika med RegexOptions.None, som i följande exempel illustreras.

if (rgx.Options == RegexOptions.None)
    Console.WriteLine("No options have been set.");
If rgx.Options = RegexOptions.None Then
    Console.WriteLine("No options have been set.")
End If

I följande avsnitt visas de alternativ som stöds av reguljära uttryck i .NET.

Standardalternativ

Alternativet RegexOptions.None anger att inga alternativ har angetts och motorn för reguljära uttryck använder sitt standardbeteende. Detta omfattar följande:

  • Mönstret tolkas som ett kanoniskt snarare än ett reguljärt ECMAScript-uttryck.

  • Mönster för reguljära uttryck matchas i indatasträngen från vänster till höger.

  • Jämförelser är skiftlägeskänsliga.

  • Språkelementen ^ och $ anger början och slutet av indatasträngen. Slutet på indatasträngen kan vara ett avslutande nytt radtecken \n .

  • Språkelementet . matchar alla tecken utom \n.

  • Alla blanksteg i ett reguljärt uttrycksmönster tolkas som ett literalt blankstegstecken.

  • Konventionerna i den aktuella kulturen används när du jämför mönstret med indatasträngen.

  • Att samla in grupper i mönstret för reguljära uttryck är både implicit och explicit.

Kommentar

Alternativet RegexOptions.None har ingen infogad motsvarighet. När alternativ för reguljära uttryck tillämpas infogat återställs standardbeteendet alternativ för alternativ genom att inaktivera ett visst alternativ. Aktiverar till exempel (?i) skiftlägesokänslig jämförelse och (?-i) återställer standardfallskänslig jämförelse.

Eftersom alternativet RegexOptions.None representerar standardbeteendet för motorn för reguljära uttryck anges det sällan uttryckligen i ett metodanrop. En konstruktor eller statisk mönstermatchningsmetod utan parameter options anropas i stället.

Skiftlägesokänslig matchning

Alternativet IgnoreCase , eller det i infogade alternativet, ger skiftlägesokänslig matchning. Som standard används höljekonventionerna för den aktuella kulturen.

I följande exempel definieras ett mönster för reguljära uttryck, \bthe\w*\b, som matchar alla ord som börjar med "the". Eftersom det första anropet Match till metoden använder standardfallskänslig jämförelse anger utdata att strängen "The" som börjar meningen inte matchas. Den matchas när Match metoden anropas med alternativ inställda på IgnoreCase.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\bthe\w*\b";
      string input = "The man then told them about that event.";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);

      Console.WriteLine();
      foreach (Match match in Regex.Matches(input, pattern,
                                            RegexOptions.IgnoreCase))
         Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found then at index 8.
//       Found them at index 18.
//
//       Found The at index 0.
//       Found then at index 8.
//       Found them at index 18.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\bthe\w*\b"
        Dim input As String = "The man then told them about that event."
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
        Console.WriteLine()
        For Each match As Match In Regex.Matches(input, pattern, _
                                                 RegexOptions.IgnoreCase)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found then at index 8.
'       Found them at index 18.
'       
'       Found The at index 0.
'       Found then at index 8.
'       Found them at index 18.

I följande exempel ändras mönster för reguljära uttryck från föregående exempel för att använda infogade alternativ i stället för parametern options för att ge skiftlägesokänslig jämförelse. Det första mönstret definierar alternativet skiftlägesokänsligt i en grupperingskonstruktion som endast gäller bokstaven "t" i strängen "the". Eftersom alternativkonstruktionen sker i början av mönstret tillämpar det andra mönstret det skiftlägesokänsliga alternativet på hela det reguljära uttrycket.

using System;
using System.Text.RegularExpressions;

public class CaseExample
{
    public static void Main()
    {
        string pattern = @"\b(?i:t)he\w*\b";
        string input = "The man then told them about that event.";
        foreach (Match match in Regex.Matches(input, pattern))
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);

        Console.WriteLine();
        pattern = @"(?i)\bthe\w*\b";
        foreach (Match match in Regex.Matches(input, pattern,
                                              RegexOptions.IgnoreCase))
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);
    }
}
// The example displays the following output:
//       Found The at index 0.
//       Found then at index 8.
//       Found them at index 18.
//
//       Found The at index 0.
//       Found then at index 8.
//       Found them at index 18.
Imports System.Text.RegularExpressions

Module CaseExample
    Public Sub Main()
        Dim pattern As String = "\b(?i:t)he\w*\b"
        Dim input As String = "The man then told them about that event."
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
        Console.WriteLine()
        pattern = "(?i)\bthe\w*\b"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
    End Sub
End Module

' The example displays the following output:
'       Found The at index 0.
'       Found then at index 8.
'       Found them at index 18.
'       
'       Found The at index 0.
'       Found then at index 8.
'       Found them at index 18.

Flerradsläge

Alternativet RegexOptions.Multiline , eller det m infogade alternativet, gör att motorn för reguljära uttryck kan hantera en indatasträng som består av flera rader. Den ändrar tolkningen av språkelementen ^ och $ så att de anger början och slutet av en rad, i stället för början och slutet av indatasträngen.

Som standard $ uppfylls endast i slutet av indatasträngen. Om du anger alternativet RegexOptions.Multiline kommer det att uppfyllas av antingen det nya radtecknet (\n) eller slutet av indatasträngen.

I inget av fallen identifieras $ teckenkombinationen vagnretur/radmatning (\r\n). $ ignorerar alltid alla vagnretur (\r). Om du vill avsluta matchningen med antingen \r\n eller \nanvänder du underuttryck i \r?$ stället för bara $. Observera att detta kommer att göra den \r del av matchningen.

I följande exempel extraheras bowlers namn och poäng och läggs till i en SortedList<TKey,TValue> samling som sorterar dem i fallande ordning. Metoden Matches anropas två gånger. I det första metodanropet är ^(\w+)\s(\d+)$ det reguljära uttrycket och inga alternativ anges. Som utdata visar, eftersom motorn för reguljära uttryck inte kan matcha indatamönstret tillsammans med början och slutet av indatasträngen, hittas inga matchningar. I det andra metodanropet ändras det reguljära uttrycket till ^(\w+)\s(\d+)\r?$ och alternativen är inställda på RegexOptions.Multiline. Som utdata visar matchas namnen och poängen och poängen visas i fallande ordning.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Multiline1Example
{
    public static void Main()
    {
        SortedList<int, string> scores = new SortedList<int, string>(new DescendingComparer1<int>());

        string input = "Joe 164\n" +
                       "Sam 208\n" +
                       "Allison 211\n" +
                       "Gwen 171\n";
        string pattern = @"^(\w+)\s(\d+)$";
        bool matched = false;

        Console.WriteLine("Without Multiline option:");
        foreach (Match match in Regex.Matches(input, pattern))
        {
            scores.Add(Int32.Parse(match.Groups[2].Value), (string)match.Groups[1].Value);
            matched = true;
        }
        if (!matched)
            Console.WriteLine("   No matches.");
        Console.WriteLine();

        // Redefine pattern to handle multiple lines.
        pattern = @"^(\w+)\s(\d+)\r*$";
        Console.WriteLine("With multiline option:");
        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
            scores.Add(Int32.Parse(match.Groups[2].Value), (string)match.Groups[1].Value);

        // List scores in descending order.
        foreach (KeyValuePair<int, string> score in scores)
            Console.WriteLine("{0}: {1}", score.Value, score.Key);
    }
}

public class DescendingComparer1<T> : IComparer<T>
{
    public int Compare(T x, T y)
    {
        return Comparer<T>.Default.Compare(x, y) * -1;
    }
}
// The example displays the following output:
//   Without Multiline option:
//      No matches.
//
//   With multiline option:
//   Allison: 211
//   Sam: 208
//   Gwen: 171
//   Joe: 164
Imports System.Collections.Generic
Imports System.Text.RegularExpressions

Module Multiline1Example
    Public Sub Main()
        Dim scores As New SortedList(Of Integer, String)(New DescendingComparer1(Of Integer)())

        Dim input As String = "Joe 164" + vbCrLf +
                              "Sam 208" + vbCrLf +
                              "Allison 211" + vbCrLf +
                              "Gwen 171" + vbCrLf
        Dim pattern As String = "^(\w+)\s(\d+)$"
        Dim matched As Boolean = False

        Console.WriteLine("Without Multiline option:")
        For Each match As Match In Regex.Matches(input, pattern)
            scores.Add(CInt(match.Groups(2).Value), match.Groups(1).Value)
            matched = True
        Next
        If Not matched Then Console.WriteLine("   No matches.")
        Console.WriteLine()

        ' Redefine pattern to handle multiple lines.
        pattern = "^(\w+)\s(\d+)\r*$"
        Console.WriteLine("With multiline option:")
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.Multiline)
            scores.Add(CInt(match.Groups(2).Value), match.Groups(1).Value)
        Next
        ' List scores in descending order. 
        For Each score As KeyValuePair(Of Integer, String) In scores
            Console.WriteLine("{0}: {1}", score.Value, score.Key)
        Next
    End Sub
End Module

Public Class DescendingComparer1(Of T) : Implements IComparer(Of T)
    Public Function Compare(x As T, y As T) As Integer _
           Implements IComparer(Of T).Compare
        Return Comparer(Of T).Default.Compare(x, y) * -1
    End Function
End Class
' The example displays the following output:
'    Without Multiline option:
'       No matches.
'    
'    With multiline option:
'    Allison: 211
'    Sam: 208
'    Gwen: 171
'    Joe: 164

Mönster för ^(\w+)\s(\d+)\r*$ reguljära uttryck definieras enligt följande tabell.

Mönster beskrivning
^ Börja i början av raden.
(\w+) Matcha ett eller flera ordtecken. Det här är den första insamlingsgruppen.
\s Matcha ett blankstegstecken.
(\d+) Matcha en eller flera decimaler. Det här är den andra insamlingsgruppen.
\r? Matcha noll eller ett vagnreturtecken.
$ Avsluta i slutet av raden.

Följande exempel motsvarar det föregående, förutom att det använder det infogade alternativet (?m) för att ange flerradsalternativet.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Multiline2Example
{
    public static void Main()
    {
        SortedList<int, string> scores = new SortedList<int, string>(new DescendingComparer<int>());

        string input = "Joe 164\n" +
                       "Sam 208\n" +
                       "Allison 211\n" +
                       "Gwen 171\n";
        string pattern = @"(?m)^(\w+)\s(\d+)\r*$";

        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
            scores.Add(Convert.ToInt32(match.Groups[2].Value), match.Groups[1].Value);

        // List scores in descending order.
        foreach (KeyValuePair<int, string> score in scores)
            Console.WriteLine("{0}: {1}", score.Value, score.Key);
    }
}

public class DescendingComparer<T> : IComparer<T>
{
    public int Compare(T x, T y)
    {
        return Comparer<T>.Default.Compare(x, y) * -1;
    }
}
// The example displays the following output:
//    Allison: 211
//    Sam: 208
//    Gwen: 171
//    Joe: 164
Imports System.Collections.Generic
Imports System.Text.RegularExpressions

Module Multiline2Example
    Public Sub Main()
        Dim scores As New SortedList(Of Integer, String)(New DescendingComparer(Of Integer)())

        Dim input As String = "Joe 164" + vbCrLf +
                              "Sam 208" + vbCrLf +
                              "Allison 211" + vbCrLf +
                              "Gwen 171" + vbCrLf
        Dim pattern As String = "(?m)^(\w+)\s(\d+)\r*$"

        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.Multiline)
            scores.Add(CInt(match.Groups(2).Value), match.Groups(1).Value)
        Next
        ' List scores in descending order. 
        For Each score As KeyValuePair(Of Integer, String) In scores
            Console.WriteLine("{0}: {1}", score.Value, score.Key)
        Next
    End Sub
End Module

Public Class DescendingComparer(Of T) : Implements IComparer(Of T)
    Public Function Compare(x As T, y As T) As Integer _
           Implements IComparer(Of T).Compare
        Return Comparer(Of T).Default.Compare(x, y) * -1
    End Function
End Class
' The example displays the following output:
'    Allison: 211
'    Sam: 208
'    Gwen: 171
'    Joe: 164

Enkelradsläge

Alternativet RegexOptions.Singleline , eller det s infogade alternativet, gör att motorn för reguljära uttryck behandlar indatasträngen som om den består av en enda rad. Det gör det genom att ändra beteendet för punkt -språkelementet (.) så att det matchar varje tecken, i stället för att matcha varje tecken förutom det nya tecknet \n.

I följande exempel visas hur beteendet för . språkelementet ändras när du använder RegexOptions.Singleline alternativet. Det reguljära uttrycket ^.+ börjar i början av strängen och matchar varje tecken. Som standard slutar matchningen i slutet av den första raden. mönstret för reguljära uttryck matchar vagnreturtecknet \r, men det matchar \ninte . Eftersom alternativet RegexOptions.Singleline tolkar hela indatasträngen som en enda rad matchar det varje tecken i indatasträngen, inklusive \n.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "^.+";
      string input = "This is one line and" + Environment.NewLine + "this is the second.";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine(Regex.Escape(match.Value));

      Console.WriteLine();
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Singleline))
         Console.WriteLine(Regex.Escape(match.Value));
   }
}
// The example displays the following output:
//       This\ is\ one\ line\ and\r
//
//       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "^.+"
        Dim input As String = "This is one line and" + vbCrLf + "this is the second."
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine(Regex.Escape(match.Value))
        Next
        Console.WriteLine()
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.SingleLine)
            Console.WriteLine(Regex.Escape(match.Value))
        Next
    End Sub
End Module
' The example displays the following output:
'       This\ is\ one\ line\ and\r
'       
'       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.

Följande exempel motsvarar det föregående, förutom att det använder det infogade alternativet (?s) för att aktivera enkelradsläge.

using System;
using System.Text.RegularExpressions;

public class SingleLineExample
{
    public static void Main()
    {
        string pattern = "(?s)^.+";
        string input = "This is one line and" + Environment.NewLine + "this is the second.";

        foreach (Match match in Regex.Matches(input, pattern))
            Console.WriteLine(Regex.Escape(match.Value));
    }
}
// The example displays the following output:
//       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.
Imports System.Text.RegularExpressions

Module SingleLineExample
    Public Sub Main()
        Dim pattern As String = "(?s)^.+"
        Dim input As String = "This is one line and" + vbCrLf + "this is the second."

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine(Regex.Escape(match.Value))
        Next
    End Sub
End Module
' The example displays the following output:
'       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.

Endast explicita avbildningar

Som standard definieras insamlingsgrupper med parenteser i mönstret för reguljära uttryck. Namngivna grupper tilldelas ett namn eller nummer med (?<alternativet underuttrycksspråk>), medan namnlösa grupper är tillgängliga per index. I objektet GroupCollection föregås namnlösa grupper av namngivna grupper.

Grupperingskonstruktioner används ofta endast för att tillämpa kvantifierare på flera språkelement, och de insamlade delsträngarna är inte intressanta. Om till exempel följande reguljära uttryck:

\b\(?((\w+),?\s?)+[\.!?]\)?

är endast avsedd att extrahera meningar som slutar med en punkt, ett utropstecken eller ett frågetecken från ett dokument, endast den resulterande meningen (som representeras av Match objektet) är av intresse. De enskilda orden i samlingen är inte det.

Det kan vara dyrt att samla in grupper som inte används senare, eftersom motorn för reguljära uttryck måste fylla både objekten och CaptureCollection samlingsobjektenGroupCollection. Alternativt kan du använda antingen RegexOptions.ExplicitCapture alternativet eller det n infogade alternativet för att ange att de enda giltiga avbildningarna uttryckligen namnges eller numrerade grupper som anges av namnunderuttryckskonstruktionen>(?<).

I följande exempel visas information om matchningar som returneras av \b\(?((\w+),?\s?)+[\.!?]\)? mönstret för reguljära uttryck när Match metoden anropas med och utan alternativet RegexOptions.ExplicitCapture . Som utdata från det första metodanropet visar fyller motorn för reguljära uttryck helt och CaptureCollection samlingsobjekten GroupCollection med information om insamlade delsträngar. Eftersom den andra metoden anropas med options inställd RegexOptions.ExplicitCapturepå samlar den inte in information om grupper.

using System;
using System.Text.RegularExpressions;

public class Explicit1Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"\b\(?((?>\w+),?\s?)+[\.!?]\)?";
        Console.WriteLine("With implicit captures:");
        foreach (Match match in Regex.Matches(input, pattern))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
        Console.WriteLine();
        Console.WriteLine("With explicit captures only:");
        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.ExplicitCapture))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
    }
}
// The example displays the following output:
//    With implicit captures:
//    The match: This is the first sentence.
//       Group 0: This is the first sentence.
//          Capture 0: This is the first sentence.
//       Group 1: sentence
//          Capture 0: This
//          Capture 1: is
//          Capture 2: the
//          Capture 3: first
//          Capture 4: sentence
//       Group 2: sentence
//          Capture 0: This
//          Capture 1: is
//          Capture 2: the
//          Capture 3: first
//          Capture 4: sentence
//    The match: Is it the beginning of a literary masterpiece?
//       Group 0: Is it the beginning of a literary masterpiece?
//          Capture 0: Is it the beginning of a literary masterpiece?
//       Group 1: masterpiece
//          Capture 0: Is
//          Capture 1: it
//          Capture 2: the
//          Capture 3: beginning
//          Capture 4: of
//          Capture 5: a
//          Capture 6: literary
//          Capture 7: masterpiece
//       Group 2: masterpiece
//          Capture 0: Is
//          Capture 1: it
//          Capture 2: the
//          Capture 3: beginning
//          Capture 4: of
//          Capture 5: a
//          Capture 6: literary
//          Capture 7: masterpiece
//    The match: I think not.
//       Group 0: I think not.
//          Capture 0: I think not.
//       Group 1: not
//          Capture 0: I
//          Capture 1: think
//          Capture 2: not
//       Group 2: not
//          Capture 0: I
//          Capture 1: think
//          Capture 2: not
//    The match: Instead, it is a nonsensical paragraph.
//       Group 0: Instead, it is a nonsensical paragraph.
//          Capture 0: Instead, it is a nonsensical paragraph.
//       Group 1: paragraph
//          Capture 0: Instead,
//          Capture 1: it
//          Capture 2: is
//          Capture 3: a
//          Capture 4: nonsensical
//          Capture 5: paragraph
//       Group 2: paragraph
//          Capture 0: Instead
//          Capture 1: it
//          Capture 2: is
//          Capture 3: a
//          Capture 4: nonsensical
//          Capture 5: paragraph
//
//    With explicit captures only:
//    The match: This is the first sentence.
//       Group 0: This is the first sentence.
//          Capture 0: This is the first sentence.
//    The match: Is it the beginning of a literary masterpiece?
//       Group 0: Is it the beginning of a literary masterpiece?
//          Capture 0: Is it the beginning of a literary masterpiece?
//    The match: I think not.
//       Group 0: I think not.
//          Capture 0: I think not.
//    The match: Instead, it is a nonsensical paragraph.
//       Group 0: Instead, it is a nonsensical paragraph.
//          Capture 0: Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Explicit1Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "\b\(?((?>\w+),?\s?)+[\.!?]\)?"
        Console.WriteLine("With implicit captures:")
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
        Console.WriteLine()
        Console.WriteLine("With explicit captures only:")
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.ExplicitCapture)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'    With implicit captures:
'    The match: This is the first sentence.
'       Group 0: This is the first sentence.
'          Capture 0: This is the first sentence.
'       Group 1: sentence
'          Capture 0: This
'          Capture 1: is
'          Capture 2: the
'          Capture 3: first
'          Capture 4: sentence
'       Group 2: sentence
'          Capture 0: This
'          Capture 1: is
'          Capture 2: the
'          Capture 3: first
'          Capture 4: sentence
'    The match: Is it the beginning of a literary masterpiece?
'       Group 0: Is it the beginning of a literary masterpiece?
'          Capture 0: Is it the beginning of a literary masterpiece?
'       Group 1: masterpiece
'          Capture 0: Is
'          Capture 1: it
'          Capture 2: the
'          Capture 3: beginning
'          Capture 4: of
'          Capture 5: a
'          Capture 6: literary
'          Capture 7: masterpiece
'       Group 2: masterpiece
'          Capture 0: Is
'          Capture 1: it
'          Capture 2: the
'          Capture 3: beginning
'          Capture 4: of
'          Capture 5: a
'          Capture 6: literary
'          Capture 7: masterpiece
'    The match: I think not.
'       Group 0: I think not.
'          Capture 0: I think not.
'       Group 1: not
'          Capture 0: I
'          Capture 1: think
'          Capture 2: not
'       Group 2: not
'          Capture 0: I
'          Capture 1: think
'          Capture 2: not
'    The match: Instead, it is a nonsensical paragraph.
'       Group 0: Instead, it is a nonsensical paragraph.
'          Capture 0: Instead, it is a nonsensical paragraph.
'       Group 1: paragraph
'          Capture 0: Instead,
'          Capture 1: it
'          Capture 2: is
'          Capture 3: a
'          Capture 4: nonsensical
'          Capture 5: paragraph
'       Group 2: paragraph
'          Capture 0: Instead
'          Capture 1: it
'          Capture 2: is
'          Capture 3: a
'          Capture 4: nonsensical
'          Capture 5: paragraph
'    
'    With explicit captures only:
'    The match: This is the first sentence.
'       Group 0: This is the first sentence.
'          Capture 0: This is the first sentence.
'    The match: Is it the beginning of a literary masterpiece?
'       Group 0: Is it the beginning of a literary masterpiece?
'          Capture 0: Is it the beginning of a literary masterpiece?
'    The match: I think not.
'       Group 0: I think not.
'          Capture 0: I think not.
'    The match: Instead, it is a nonsensical paragraph.
'       Group 0: Instead, it is a nonsensical paragraph.
'          Capture 0: Instead, it is a nonsensical paragraph.

Mönster för\b\(?((?>\w+),?\s?)+[\.!?]\)? reguljära uttryck definieras enligt följande tabell.

Mönster beskrivning
\b Börja vid en ordgräns.
\(? Matcha noll eller en förekomst av den inledande parentesen ("(").
(?>\w+),? Matcha ett eller flera ordtecken följt av noll eller ett kommatecken. Backa inte när du matchar ordtecken.
\s? Matcha noll eller ett blankstegstecken.
((\w+),?\s?)+ Matcha kombinationen av ett eller flera ordtecken, noll eller ett kommatecken och noll eller ett blankstegstecken en eller flera gånger.
[\.!?]\)? Matcha någon av de tre skiljetecken, följt av noll eller en avslutande parentes (")").

Du kan också använda det (?n) infogade elementet för att förhindra automatiska avbildningar. I följande exempel ändras det tidigare reguljära uttrycksmönstret så att det (?n) infogade elementet används i stället för alternativet RegexOptions.ExplicitCapture .

using System;
using System.Text.RegularExpressions;

public class Explicit2Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"(?n)\b\(?((?>\w+),?\s?)+[\.!?]\)?";

        foreach (Match match in Regex.Matches(input, pattern))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
    }
}
// The example displays the following output:
//       The match: This is the first sentence.
//          Group 0: This is the first sentence.
//             Capture 0: This is the first sentence.
//       The match: Is it the beginning of a literary masterpiece?
//          Group 0: Is it the beginning of a literary masterpiece?
//             Capture 0: Is it the beginning of a literary masterpiece?
//       The match: I think not.
//          Group 0: I think not.
//             Capture 0: I think not.
//       The match: Instead, it is a nonsensical paragraph.
//          Group 0: Instead, it is a nonsensical paragraph.
//             Capture 0: Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Explicit2Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "(?n)\b\(?((?>\w+),?\s?)+[\.!?]\)?"

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'       The match: This is the first sentence.
'          Group 0: This is the first sentence.
'             Capture 0: This is the first sentence.
'       The match: Is it the beginning of a literary masterpiece?
'          Group 0: Is it the beginning of a literary masterpiece?
'             Capture 0: Is it the beginning of a literary masterpiece?
'       The match: I think not.
'          Group 0: I think not.
'             Capture 0: I think not.
'       The match: Instead, it is a nonsensical paragraph.
'          Group 0: Instead, it is a nonsensical paragraph.
'             Capture 0: Instead, it is a nonsensical paragraph.

Slutligen kan du använda elementet (?n:) infogad grupp för att förhindra automatiska avbildningar grupp för grupp. I följande exempel ändras det tidigare mönstret för att förhindra icke namngivna avbildningar i den yttre gruppen, ((?>\w+),?\s?). Observera att detta undertrycker icke namngivna avbildningar även i den inre gruppen.

using System;
using System.Text.RegularExpressions;

public class Explicit3Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"\b\(?(?n:(?>\w+),?\s?)+[\.!?]\)?";

        foreach (Match match in Regex.Matches(input, pattern))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
    }
}
// The example displays the following output:
//       The match: This is the first sentence.
//          Group 0: This is the first sentence.
//             Capture 0: This is the first sentence.
//       The match: Is it the beginning of a literary masterpiece?
//          Group 0: Is it the beginning of a literary masterpiece?
//             Capture 0: Is it the beginning of a literary masterpiece?
//       The match: I think not.
//          Group 0: I think not.
//             Capture 0: I think not.
//       The match: Instead, it is a nonsensical paragraph.
//          Group 0: Instead, it is a nonsensical paragraph.
//             Capture 0: Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Explicit3Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "\b\(?(?n:(?>\w+),?\s?)+[\.!?]\)?"

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'       The match: This is the first sentence.
'          Group 0: This is the first sentence.
'             Capture 0: This is the first sentence.
'       The match: Is it the beginning of a literary masterpiece?
'          Group 0: Is it the beginning of a literary masterpiece?
'             Capture 0: Is it the beginning of a literary masterpiece?
'       The match: I think not.
'          Group 0: I think not.
'             Capture 0: I think not.
'       The match: Instead, it is a nonsensical paragraph.
'          Group 0: Instead, it is a nonsensical paragraph.
'             Capture 0: Instead, it is a nonsensical paragraph.

Kompilerade reguljära uttryck

Kommentar

Använd där det är möjligt källgenererade reguljära uttryck i stället för att kompilera reguljära uttryck med hjälp av RegexOptions.Compiled alternativet . Källgenerering kan hjälpa din app att starta snabbare, köra snabbare och bli mer trimmad. Information om när källgenerering är möjligt finns i När du ska använda den.

Som standard tolkas reguljära uttryck i .NET. När ett Regex objekt instansieras eller en statisk Regex metod anropas parsas mönstret för reguljära uttryck i en uppsättning anpassade opcodes, och en tolk använder dessa opcodes för att köra det reguljära uttrycket. Detta innebär en kompromiss: kostnaden för att initiera motorn för reguljära uttryck minimeras på bekostnad av körningsprestanda.

Du kan använda kompilerade i stället för tolkade reguljära uttryck med hjälp av alternativet RegexOptions.Compiled . I det här fallet, när ett mönster skickas till motorn för reguljära uttryck, parsas det till en uppsättning opcodes och konverteras sedan till det gemensamma mellanliggande språket (CIL), som kan skickas direkt till den gemensamma språkkörningen. Kompilerade reguljära uttryck maximerar körningsprestanda på bekostnad av initieringstiden.

Kommentar

Ett reguljärt uttryck kan bara kompileras genom att RegexOptions.Compiled ange värdet till parametern options för en Regex klasskonstruktor eller en statisk mönstermatchningsmetod. Det är inte tillgängligt som ett infogat alternativ.

Du kan använda kompilerade reguljära uttryck i anrop till både statiska uttryck och reguljära instansuttryck. I statiska reguljära uttryck skickas RegexOptions.Compiled alternativet till parametern options för metoden mönstermatchning med reguljära uttryck. I instansen av reguljära uttryck skickas det till parametern options för Regex klasskonstruktorn. I båda fallen resulterar det i förbättrad prestanda.

Den här prestandaförbättringen sker dock endast under följande förhållanden:

  • Ett Regex objekt som representerar ett visst reguljärt uttryck används i flera anrop till mönstermatchningsmetoder för reguljära uttryck.

  • Objektet Regex får inte gå utanför omfånget, så det kan återanvändas.

  • Ett statiskt reguljärt uttryck används i flera anrop till mönstermatchningsmetoder för reguljära uttryck. (Prestandaförbättringen är möjlig eftersom reguljära uttryck som används i statiska metodanrop cachelagras av motorn för reguljära uttryck.)

Kommentar

Alternativet RegexOptions.Compiled är inte relaterat till den föråldrade Regex.CompileToAssembly metoden, som skapar en specialsammansättning som innehåller fördefinierade, kompilerade reguljära uttryck.

Ignorera tomt utrymme

Som standard är tomt utrymme i ett reguljärt uttrycksmönster betydande. den tvingar motorn för reguljära uttryck att matcha ett blankstegstecken i indatasträngen. Därför är det reguljära uttrycket "\b\w+\s" och " "\b\w+ ungefär likvärdiga reguljära uttryck. När taltecknet (#) dessutom påträffas i ett reguljärt uttrycksmönster tolkas det som ett literaltecken som ska matchas.

Alternativet RegexOptions.IgnorePatternWhitespace eller det x infogade alternativet ändrar det här standardbeteendet på följande sätt:

  • Ej inkapslade blanksteg i mönstret för reguljära uttryck ignoreras. Om du vill vara en del av ett mönster för reguljära uttryck måste blankstegstecken vara undantagna (till exempel som \s eller "\ ").

  • Taltecknet (#) tolkas som början på en kommentar i stället för som ett literaltecken. All text i reguljärt uttrycksmönster från # tecknet till antingen nästa \n tecken eller till slutet av strängen tolkas som en kommentar.

I följande fall ignoreras dock inte blankstegstecken i ett reguljärt uttryck, även om du använder alternativet RegexOptions.IgnorePatternWhitespace :

  • Blanksteg i en teckenklass tolkas alltid bokstavligen. Mönstret [ .,;:] för reguljära uttryck matchar till exempel ett enskilt blankstegstecken, punkttecken, kommatecken, semikolon eller kolon.

  • Tomt utrymme tillåts inte inom en hakparenteserad kvantifierare, till exempel {n}, {n,} och {n,m.} Det reguljära uttrycksmönstret \d{1, 3} kan till exempel inte matcha några sekvenser med siffror från en till tre siffror eftersom det innehåller ett blankstegstecken.

  • Blanksteg tillåts inte i en teckensekvens som introducerar ett språkelement. Till exempel:

    • Språkelementets (?:underuttryck) representerar en icke-kapslingsgrupp och delen (?: av elementet kan inte ha inbäddade blanksteg. Underuttryck för mönster (? :genererar en ArgumentException vid körning eftersom motorn för reguljära uttryck inte kan parsa mönstret, och underuttrycksmönstret( ?:) misslyckas med att matcha underuttryck.)

    • Språkelementnamnet\p{}, som representerar en Unicode-kategori eller ett namngivet block, kan inte innehålla inbäddade blanksteg i \p{ delen av elementet. Om du inkluderar ett tomt utrymme genererar elementet ett ArgumentException vid körning.

Om du aktiverar det här alternativet kan du förenkla reguljära uttryck som ofta är svåra att parsa och förstå. Det förbättrar läsbarheten och gör det möjligt att dokumentera ett reguljärt uttryck.

I följande exempel definieras följande mönster för reguljära uttryck:

\b \(? ( (?>\w+) ,?\s? )+ [\.!?] \)? # Matches an entire sentence.

Det här mönstret liknar det mönster som definierats i avsnittet Endast explicita avbildningar, förutom att det använder RegexOptions.IgnorePatternWhitespace alternativet för att ignorera tomt mönsterutrymme.

using System;
using System.Text.RegularExpressions;

public class Whitespace1Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"\b \(? ( (?>\w+) ,?\s? )+ [\.!?] \)? # Matches an entire sentence.";

        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnorePatternWhitespace))
            Console.WriteLine(match.Value);
    }
}
// The example displays the following output:
//       This is the first sentence.
//       Is it the beginning of a literary masterpiece?
//       I think not.
//       Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Whitespace1Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "\b \(? ( (?>\w+) ,?\s? )+  [\.!?] \)? # Matches an entire sentence."

        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnorePatternWhitespace)
            Console.WriteLine(match.Value)
        Next
    End Sub
End Module
' The example displays the following output:
'       This is the first sentence.
'       Is it the beginning of a literary masterpiece?
'       I think not.
'       Instead, it is a nonsensical paragraph.

I följande exempel används det infogade alternativet (?x) för att ignorera mönstrets blanksteg.

using System;
using System.Text.RegularExpressions;

public class Whitespace2Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"(?x)\b \(? ( (?>\w+) ,?\s? )+  [\.!?] \)? # Matches an entire sentence.";

        foreach (Match match in Regex.Matches(input, pattern))
            Console.WriteLine(match.Value);
    }
}
// The example displays the following output:
//       This is the first sentence.
//       Is it the beginning of a literary masterpiece?
//       I think not.
//       Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Whitespace2Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "(?x)\b \(? ( (?>\w+) ,?\s? )+  [\.!?] \)? # Matches an entire sentence."

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine(match.Value)
        Next
    End Sub
End Module
' The example displays the following output:
'       This is the first sentence.
'       Is it the beginning of a literary masterpiece?
'       I think not.
'       Instead, it is a nonsensical paragraph.

Höger-till-vänster-läge

Som standard söker motorn för reguljära uttryck från vänster till höger. Du kan ändra sökriktningen med hjälp RegexOptions.RightToLeft av alternativet . Sökningen från höger till vänster börjar automatiskt vid strängens sista teckenposition. För mönstermatchningsmetoder som innehåller en startpositionsparameter, till exempel Regex.Match(String, Int32), är den angivna startpositionen indexet för den högra teckenpositionen där sökningen ska börja.

Kommentar

Mönsterläge från höger till vänster är endast tillgängligt genom att ange RegexOptions.RightToLeft värdet till parametern options för en Regex klasskonstruktor eller statisk mönstermatchningsmetod. Den är inte tillgänglig som ett infogat alternativ.

Exempel

Det reguljära uttrycket \bb\w+\s matchar ord med två eller flera tecken som börjar med bokstaven "b" och följs av ett blankstegstecken. I följande exempel består indatasträngen av tre ord som innehåller ett eller flera "b"-tecken. De första och andra orden börjar med "b" och det tredje ordet slutar med "b". Som utdata från sökexemplet från höger till vänster visar matchar endast de första och andra orden mönstret för reguljära uttryck, där det andra ordet matchas först.

using System;
using System.Text.RegularExpressions;

public class RTL1Example
{
    public static void Main()
    {
        string pattern = @"\bb\w+\s";
        string input = "build band tab";
        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.RightToLeft))
            Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
    }
}
// The example displays the following output:
//       'band ' found at position 6.
//       'build ' found at position 0.
Imports System.Text.RegularExpressions

Module RTL1Example
    Public Sub Main()
        Dim pattern As String = "\bb\w+\s"
        Dim input As String = "build band tab"
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.RightToLeft)
            Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       'band ' found at position 6.
'       'build ' found at position 0.

Utvärderingsordning

Alternativet RegexOptions.RightToLeft ändrar sökriktningen och ändrar även i vilken ordning mönstret för reguljära uttryck utvärderas. I en sökning från höger till vänster läss sökmönstret från höger till vänster. Den här skillnaden är viktig eftersom den kan påverka saker som insamlingsgrupper och backreferences. Uttrycket Regex.Match("abcabc", @"\1(abc)", RegexOptions.RightToLeft) hittar till exempel en matchning abcabc, men i en sökning från vänster till höger (Regex.Match("abcabc", @"\1(abc)", RegexOptions.None)) hittas ingen matchning. Det beror på att elementet (abc) måste utvärderas innan det numrerade grupperingselementet (\1) för att en matchning ska hittas.

Lookahead och lookbehind försäkran

Platsen för en matchning för en lookahead-försäkran ((?=subexpression)) eller lookbehind ((?<=subexpression)) ändras inte i en sökning från höger till vänster. Lookahead-försäkran ser till höger om den aktuella matchningsplatsen. lookbehind-försäkran ser till vänster om den aktuella matchningsplatsen.

Dricks

Oavsett om en sökning är från höger till vänster eller inte implementeras lookbehinds med hjälp av en höger-till-vänster-sökning som börjar på den aktuella matchningsplatsen.

Till exempel använder det reguljära uttrycket (?<=\d{1,2}\s)\w+,\s\d{4} lookbehind-försäkran för att testa för ett datum som föregår ett månadsnamn. Det reguljära uttrycket matchar sedan månaden och året. Information om lookahead- och lookbehind-försäkran finns i Grupperingskonstruktioner.

using System;
using System.Text.RegularExpressions;

public class RTL2Example
{
    public static void Main()
    {
        string[] inputs = { "1 May, 1917", "June 16, 2003" };
        string pattern = @"(?<=\d{1,2}\s)\w+,\s\d{4}";

        foreach (string input in inputs)
        {
            Match match = Regex.Match(input, pattern, RegexOptions.RightToLeft);
            if (match.Success)
                Console.WriteLine("The date occurs in {0}.", match.Value);
            else
                Console.WriteLine("{0} does not match.", input);
        }
    }
}

// The example displays the following output:
//       The date occurs in May, 1917.
//       June 16, 2003 does not match.
Imports System.Text.RegularExpressions

Module RTL2Example
    Public Sub Main()
        Dim inputs() As String = {"1 May, 1917", "June 16, 2003"}
        Dim pattern As String = "(?<=\d{1,2}\s)\w+,\s\d{4}"

        For Each input As String In inputs
            Dim match As Match = Regex.Match(input, pattern, RegexOptions.RightToLeft)
            If match.Success Then
                Console.WriteLine("The date occurs in {0}.", match.Value)
            Else
                Console.WriteLine("{0} does not match.", input)
            End If
        Next
    End Sub
End Module

' The example displays the following output:
'       The date occurs in May, 1917.
'       June 16, 2003 does not match.

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

Mönster beskrivning
(?<=\d{1,2}\s) Matchningens början måste föregås av en eller två decimalsiffror följt av ett blanksteg.
\w+ Matcha ett eller flera ordtecken.
, Matcha ett kommatecken.
\s Matcha ett blankstegstecken.
\d{4} Matcha fyra decimalsiffror.

ECMAScript-matchningsbeteende

Som standard använder motorn för reguljära uttryck kanoniskt beteende vid matchning av ett mönster för reguljära uttryck för att mata in text. Du kan dock instruera motorn för reguljära uttryck att använda ECMAScript-matchningsbeteende genom att ange alternativet RegexOptions.ECMAScript .

Kommentar

ECMAScript-kompatibelt beteende är endast tillgängligt genom att RegexOptions.ECMAScript ange värdet till parametern options för en Regex klasskonstruktor eller statisk mönstermatchningsmetod. Den är inte tillgänglig som ett infogat alternativ.

Alternativet RegexOptions.ECMAScript kan endast kombineras med RegexOptions.IgnoreCase alternativen och RegexOptions.Multiline . Användningen av andra alternativ i ett reguljärt uttryck resulterar i en ArgumentOutOfRangeException.

Beteendet för ECMAScript och kanoniska reguljära uttryck skiljer sig åt inom tre områden: teckenklasssyntax, självrefenserande grupper och tolkning av oktal kontra backreference.

  • Teckenklasssyntax. Eftersom kanoniska reguljära uttryck stöder Unicode, medan ECMAScript inte gör det, har teckenklasser i ECMAScript en mer begränsad syntax och vissa teckenklassspråkelement har en annan betydelse. ECMAScript stöder till exempel inte språkelement som kategorin Unicode eller blockelement \p och \P. På samma sätt motsvarar elementet \w , som matchar ett ordtecken, teckenklassen [a-zA-Z_0-9] när du använder ECMAScript och [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}\p{Lm}] när du använder kanoniskt beteende. Mer information finns i Teckenklasser.

    I följande exempel visas skillnaden mellan kanonisk och ECMAScript-mönstermatchning. Det definierar ett reguljärt uttryck, \b(\w+\s*)+, som matchar ord följt av blankstegstecken. Indata består av två strängar, en som använder den latinska teckenuppsättningen och den andra som använder den kyrilliska teckenuppsättningen. Som utdata visar kan anropet till metoden Regex.IsMatch(String, String, RegexOptions) som använder ECMAScript-matchning inte matcha de kyrilliska orden, medan metodanropet som använder kanonisk matchning matchar dessa ord.

    using System;
    using System.Text.RegularExpressions;
    
    public class EcmaScriptExample
    {
        public static void Main()
        {
            string[] values = { "целый мир", "the whole world" };
            string pattern = @"\b(\w+\s*)+";
            foreach (var value in values)
            {
                Console.Write("Canonical matching: ");
                if (Regex.IsMatch(value, pattern))
                    Console.WriteLine("'{0}' matches the pattern.", value);
                else
                    Console.WriteLine("{0} does not match the pattern.", value);
    
                Console.Write("ECMAScript matching: ");
                if (Regex.IsMatch(value, pattern, RegexOptions.ECMAScript))
                    Console.WriteLine("'{0}' matches the pattern.", value);
                else
                    Console.WriteLine("{0} does not match the pattern.", value);
                Console.WriteLine();
            }
        }
    }
    // The example displays the following output:
    //       Canonical matching: 'целый мир' matches the pattern.
    //       ECMAScript matching: целый мир does not match the pattern.
    //
    //       Canonical matching: 'the whole world' matches the pattern.
    //       ECMAScript matching: 'the whole world' matches the pattern.
    
    Imports System.Text.RegularExpressions
    
    Module Ecma1Example
        Public Sub Main()
            Dim values() As String = {"целый мир", "the whole world"}
            Dim pattern As String = "\b(\w+\s*)+"
            For Each value In values
                Console.Write("Canonical matching: ")
                If Regex.IsMatch(value, pattern) Then
                    Console.WriteLine("'{0}' matches the pattern.", value)
                Else
                    Console.WriteLine("{0} does not match the pattern.", value)
                End If
    
                Console.Write("ECMAScript matching: ")
                If Regex.IsMatch(value, pattern, RegexOptions.ECMAScript) Then
                    Console.WriteLine("'{0}' matches the pattern.", value)
                Else
                    Console.WriteLine("{0} does not match the pattern.", value)
                End If
                Console.WriteLine()
            Next
        End Sub
    End Module
    ' The example displays the following output:
    '       Canonical matching: 'целый мир' matches the pattern.
    '       ECMAScript matching: целый мир does not match the pattern.
    '       
    '       Canonical matching: 'the whole world' matches the pattern.
    '       ECMAScript matching: 'the whole world' matches the pattern.
    
  • Självrefererande grupper. En reguljär uttrycksavbildningsklass med en backreference till sig själv måste uppdateras med varje avbildnings-iteration. Som följande exempel visar gör den här funktionen att det reguljära uttrycket ((a+)(\1) ?)+ kan matcha indatasträngen " aa aaaa aaaaaa " när du använder ECMAScript, men inte när du använder kanonisk matchning.

    using System;
    using System.Text.RegularExpressions;
    
    public class EcmaScript2Example
    {
        static string pattern;
    
        public static void Main()
        {
            string input = "aa aaaa aaaaaa ";
            pattern = @"((a+)(\1) ?)+";
    
            // Match input using canonical matching.
            AnalyzeMatch(Regex.Match(input, pattern));
    
            // Match input using ECMAScript.
            AnalyzeMatch(Regex.Match(input, pattern, RegexOptions.ECMAScript));
        }
    
        private static void AnalyzeMatch(Match m)
        {
            if (m.Success)
            {
                Console.WriteLine("'{0}' matches {1} at position {2}.",
                                  pattern, m.Value, m.Index);
                int grpCtr = 0;
                foreach (Group grp in m.Groups)
                {
                    Console.WriteLine("   {0}: '{1}'", grpCtr, grp.Value);
                    grpCtr++;
                    int capCtr = 0;
                    foreach (Capture cap in grp.Captures)
                    {
                        Console.WriteLine("      {0}: '{1}'", capCtr, cap.Value);
                        capCtr++;
                    }
                }
            }
            else
            {
                Console.WriteLine("No match found.");
            }
            Console.WriteLine();
        }
    }
    // The example displays the following output:
    //    No match found.
    //
    //    '((a+)(\1) ?)+' matches aa aaaa aaaaaa  at position 0.
    //       0: 'aa aaaa aaaaaa '
    //          0: 'aa aaaa aaaaaa '
    //       1: 'aaaaaa '
    //          0: 'aa '
    //          1: 'aaaa '
    //          2: 'aaaaaa '
    //       2: 'aa'
    //          0: 'aa'
    //          1: 'aa'
    //          2: 'aa'
    //       3: 'aaaa '
    //          0: ''
    //          1: 'aa '
    //          2: 'aaaa '
    
    Imports System.Text.RegularExpressions
    
    Module Ecma2Example
        Dim pattern As String
    
        Public Sub Main()
            Dim input As String = "aa aaaa aaaaaa "
            pattern = "((a+)(\1) ?)+"
    
            ' Match input using canonical matching.
            AnalyzeMatch(Regex.Match(input, pattern))
    
            ' Match input using ECMAScript.
            AnalyzeMatch(Regex.Match(input, pattern, RegexOptions.ECMAScript))
        End Sub
    
        Private Sub AnalyzeMatch(m As Match)
            If m.Success Then
                Console.WriteLine("'{0}' matches {1} at position {2}.",
                                  pattern, m.Value, m.Index)
                Dim grpCtr As Integer = 0
                For Each grp As Group In m.Groups
                    Console.WriteLine("   {0}: '{1}'", grpCtr, grp.Value)
                    grpCtr += 1
                    Dim capCtr As Integer = 0
                    For Each cap As Capture In grp.Captures
                        Console.WriteLine("      {0}: '{1}'", capCtr, cap.Value)
                        capCtr += 1
                    Next
                Next
            Else
                Console.WriteLine("No match found.")
            End If
            Console.WriteLine()
        End Sub
    End Module
    ' The example displays the following output:
    '    No match found.
    '    
    '    '((a+)(\1) ?)+' matches aa aaaa aaaaaa  at position 0.
    '       0: 'aa aaaa aaaaaa '
    '          0: 'aa aaaa aaaaaa '
    '       1: 'aaaaaa '
    '          0: 'aa '
    '          1: 'aaaa '
    '          2: 'aaaaaa '
    '       2: 'aa'
    '          0: 'aa'
    '          1: 'aa'
    '          2: 'aa'
    '       3: 'aaaa '
    '          0: ''
    '          1: 'aa '
    '          2: 'aaaa '
    

    Det reguljära uttrycket definieras enligt följande tabell.

    Mönster beskrivning
    (a+) Matcha bokstaven "a" en eller flera gånger. Det här är den andra insamlingsgruppen.
    (\1) Matcha delsträngen som fångas av den första insamlingsgruppen. Det här är den tredje insamlingsgruppen.
    ? Matcha noll eller ett blankstegstecken.
    ((a+)(\1) ?)+ Matcha mönstret för ett eller flera "a"-tecken följt av en sträng som matchar den första insamlingsgruppen följt av noll eller ett blankstegstecken en eller flera gånger. Det här är den första insamlingsgruppen.
  • Lösning av tvetydigheter mellan oktala escapes och backreferences. I följande tabell sammanfattas skillnaderna i oktal kontra backreference-tolkning av kanoniska och ECMAScript reguljära uttryck.

    Regular expression Kanoniskt beteende ECMAScript-beteende
    \0 följt av 0 till 2 oktala siffror Tolka som en oktal. Till exempel \044 tolkas alltid som ett oktalt värde och betyder "$". Samma beteende.
    \ följt av en siffra från 1 till 9, följt av inga ytterligare decimaltal, Tolka som en backreference. Det innebär till exempel \9 alltid backreference 9, även om det inte finns någon nionde insamlingsgrupp. Om insamlingsgruppen inte finns genererar parsern för reguljära uttryck en ArgumentException. Om det finns en enda decimaltalsavbildningsgrupp, backreference till den siffran. Annars tolkar du värdet som en literal.
    \ följt av en siffra från 1 till 9 följt av ytterligare decimalsiffror Tolka siffrorna som ett decimalvärde. Om insamlingsgruppen finns tolkar du uttrycket som en backreference.

    Annars tolkar du de inledande oktala siffrorna upp till oktal 377; det vill: tänk bara på de låga 8 bitarna av värdet. Tolka de återstående siffrorna som literaler. Om det till exempel finns en samlad grupp 300 i uttrycket \3000tolkar du som backreference 300. Om det inte finns någon insamlingsgrupp 300 tolkar du som oktal 300 följt av 0.
    Tolka som en backreference genom att konvertera så många siffror som möjligt till ett decimalvärde som kan referera till en avbildning. Om inga siffror kan konverteras tolkas som en oktal med hjälp av de inledande oktala siffrorna upp till oktal 377; tolka de återstående siffrorna som literaler.

Jämför med den invarianta kulturen

När motorn för reguljära uttryck utför skiftlägesokänsliga jämförelser använder den som standard höljekonventionerna i den aktuella kulturen för att fastställa motsvarande versaler och gemener.

Det här beteendet är dock inte önskvärt för vissa typer av jämförelser, särskilt när du jämför användarindata med namnen på systemresurser, till exempel lösenord, filer eller URL:er. I följande exempel visas ett sådant scenario. Koden är avsedd att blockera åtkomst till alla resurser vars URL föregås av FILE://. Det reguljära uttrycket försöker matcha skiftlägeskänsligt med strängen med hjälp av det reguljära uttrycket $FILE://. Men när den nuvarande systemkulturen är tr-TR (Turkish-Türkiye) är "I" inte versaler motsvarande "i". Därför returnerar falseanropet Regex.IsMatch till metoden och åtkomst till filen tillåts.

CultureInfo defaultCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");

string input = "file://c:/Documents.MyReport.doc";
string pattern = "FILE://";

Console.WriteLine("Culture-sensitive matching ({0} culture)...",
                  Thread.CurrentThread.CurrentCulture.Name);
if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
    Console.WriteLine("URLs that access files are not allowed.");
else
    Console.WriteLine("Access to {0} is allowed.", input);

Thread.CurrentThread.CurrentCulture = defaultCulture;
// The example displays the following output:
//       Culture-sensitive matching (tr-TR culture)...
//       Access to file://c:/Documents.MyReport.doc is allowed.
Dim defaultCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
Thread.CurrentThread.CurrentCulture = New CultureInfo("tr-TR")

Dim input As String = "file://c:/Documents.MyReport.doc"
Dim pattern As String = "$FILE://"

Console.WriteLine("Culture-sensitive matching ({0} culture)...",
                  Thread.CurrentThread.CurrentCulture.Name)
If Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase) Then
    Console.WriteLine("URLs that access files are not allowed.")
Else
    Console.WriteLine("Access to {0} is allowed.", input)
End If

Thread.CurrentThread.CurrentCulture = defaultCulture
' The example displays the following output:
'       Culture-sensitive matching (tr-TR culture)...
'       Access to file://c:/Documents.MyReport.doc is allowed.

Kommentar

Mer information om strängjämförelser som är skiftlägeskänsliga och som använder den invarianta kulturen finns i Metodtips för att använda strängar.

I stället för att använda skiftlägesokänsliga jämförelser av den aktuella kulturen kan du ange RegexOptions.CultureInvariant alternativet att ignorera kulturella skillnader i språk och använda konventionerna i den invarianta kulturen.

Kommentar

Jämförelse med den invarianta kulturen är endast tillgänglig genom att RegexOptions.CultureInvariant ange värdet till parametern options för en Regex klasskonstruktor eller statisk mönstermatchningsmetod. Den är inte tillgänglig som ett infogat alternativ.

Följande exempel är identiskt med föregående exempel, förutom att den statiska Regex.IsMatch(String, String, RegexOptions) metoden anropas med alternativ som innehåller RegexOptions.CultureInvariant. Även när den aktuella kulturen är inställd på turkiska (Türkiye) kan motorn för reguljära uttryck matcha "FILE" och "file" och blockera åtkomst till filresursen.

CultureInfo defaultCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");

string input = "file://c:/Documents.MyReport.doc";
string pattern = "FILE://";

Console.WriteLine("Culture-insensitive matching...");
if (Regex.IsMatch(input, pattern,
                  RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
    Console.WriteLine("URLs that access files are not allowed.");
else
    Console.WriteLine("Access to {0} is allowed.", input);

Thread.CurrentThread.CurrentCulture = defaultCulture;
// The example displays the following output:
//       Culture-insensitive matching...
//       URLs that access files are not allowed.
Dim defaultCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
Thread.CurrentThread.CurrentCulture = New CultureInfo("tr-TR")

Dim input As String = "file://c:/Documents.MyReport.doc"
Dim pattern As String = "$FILE://"

Console.WriteLine("Culture-insensitive matching...")
If Regex.IsMatch(input, pattern,
               RegexOptions.IgnoreCase Or RegexOptions.CultureInvariant) Then
    Console.WriteLine("URLs that access files are not allowed.")
Else
    Console.WriteLine("Access to {0} is allowed.", input)
End If
Thread.CurrentThread.CurrentCulture = defaultCulture
' The example displays the following output:
'        Culture-insensitive matching...
'        URLs that access files are not allowed.

Icke-bakåtspårningsläge

Som standard. NET:s regexmotor använder backtracking för att försöka hitta mönstermatchningar. En backtracking-motor är en motor som försöker matcha ett mönster, och om det misslyckas går tillbaka och försöker matcha ett alternativt mönster och så vidare. En backtracking-motor är mycket snabb för typiska fall, men saktar ner när antalet mönsterväxlingar ökar, vilket kan leda till katastrofal backtracking. Alternativet RegexOptions.NonBacktracking , som introducerades i .NET 7, använder inte backtracking och undviker det värsta scenariot. Målet är att ge konsekvent bra beteende, oavsett vilka indata som genomsöks.

Alternativet RegexOptions.NonBacktracking stöder inte allt som de andra inbyggda motorerna stöder. I synnerhet kan alternativet inte användas tillsammans med RegexOptions.RightToLeft eller RegexOptions.ECMAScript. Det tillåter inte heller följande konstruktioner i mönstret:

  • Atomiska grupper
  • Backreferences
  • Balansera grupper
  • Villkorssatser
  • Lösningar
  • Starta fästpunkter (\G)

RegexOptions.NonBacktracking har också en subtil skillnad när det gäller utförande. Om en avbildningsgrupp finns i en loop tillhandahåller de flesta regex-motorer (non-.NET) endast det senast matchade värdet för avbildningen. Emellertid. NET:s regexmotor spårar alla värden som samlas in i en loop och ger åtkomst till dem. Alternativet RegexOptions.NonBacktracking är som de flesta andra regex-implementeringar och har endast stöd för att tillhandahålla den slutliga avbildningen.

Mer information om backtracking finns i Backtracking i reguljära uttryck.

Se även