Háttérszerkezetek reguláris kifejezésekben

A háttérrendszerek kényelmes módot biztosítanak egy sztring ismétlődő karakterének vagy alsztringjeinek azonosítására. Ha például a bemeneti sztring egy tetszőleges részsztring több előfordulását tartalmazza, az első előfordulást egy rögzítési csoporttal egyezheti meg, majd egy visszalépéssel egyezhet az alsztring későbbi előfordulásaival.

Feljegyzés

A rendszer külön szintaxissal hivatkozik a névvel ellátott és számozott rögzítési csoportokra a helyettesítő sztringekben. További információ: Helyettesítések.

A .NET külön nyelvi elemeket határoz meg a számozott és elnevezett rögzítési csoportokra való hivatkozáshoz. A csoportok rögzítéséről további információt a Csoportosítási szerkezetek című témakörben talál.

Számozott háttérrendszerek

A számozott háttérrendszer a következő szintaxist használja:

\Szám

ahol a szám a rögzítési csoport sorszáma a reguláris kifejezésben. Például \4 egyezik a negyedik rögzítési csoport tartalmával. Ha a szám nincs definiálva a reguláris kifejezési mintában, elemzési hiba lép fel, és a reguláris kifejezésmotor egy ArgumentException. A reguláris kifejezés \b(\w+)\s\1 például érvényes, mert (\w+) a kifejezés első és egyetlen csoportját rögzíti. Másrészt érvénytelen, \b(\w+)\s\2 és argumentumkivételt ad ki, mert nincs számozott rögzítési \2csoport. Ezenkívül ha a szám egy rögzített csoportot azonosít egy adott sorrendi pozícióban, de a rögzítési csoporthoz a sorszámtól eltérő numerikus név lett hozzárendelve, akkor a reguláris kifejezéselemző egy ArgumentException.

Figyelje meg az azonos jelölést használó oktális feloldókódok (például \16) és \a számhátrések közötti kétértelműséget. Ezt a kétértelműséget a következőképpen oldjuk meg:

  • A kifejezéseket \1\9 a rendszer mindig háttérrendszerként értelmezi, nem pedig oktális kódként.

  • Ha egy többdimenziós kifejezés első számjegye 8 vagy 9 (például \80 vagy \91), akkor a kifejezés literálként értelmezve.

  • A nagyobb és az újabb \10 kifejezések akkor tekinthetők visszalépésnek, ha az adott számnak megfelelő visszalépés van; ellenkező esetben oktális kódként értelmezi őket.

  • Ha egy reguláris kifejezés egy nem definiált csoportszámra vonatkozó visszalépést tartalmaz, elemzési hiba lép fel, és a reguláris kifejezésmotor egy ArgumentException.

Ha a kétértelműség probléma, használhatja a \k<név> jelölését, amely egyértelmű, és nem téveszthető össze az oktális karakterkódokkal. Hasonlóképpen, a hexadecimális kódok, például \xdd egyértelműek, és nem téveszthetők össze a háttérkódokkal.

Az alábbi példa egy sztringben található dupla szókarakterekre mutat. Egy reguláris kifejezést határoz meg, (\w)\1amely a következő elemekből áll.

Elem Leírás
(\w) Egyezik egy szó karakterével, és rendelje hozzá az első rögzítési csoporthoz.
\1 Egyezzen meg az első rögzítési csoport értékével megegyező következő karakternek.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(\w)\1";
      string input = "trellis llama webbing dresser swagger";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found '{0}' at position {1}.",
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'll' at position 3.
//       Found 'll' at position 8.
//       Found 'bb' at position 16.
//       Found 'ss' at position 25.
//       Found 'gg' at position 33.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(\w)\1"
        Dim input As String = "trellis llama webbing dresser swagger"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found '{0}' at position {1}.", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found 'll' at position 3.
'       Found 'll' at position 8.
'       Found 'bb' at position 16.
'       Found 'ss' at position 25.
'       Found 'gg' at position 33.

Elnevezett háttérrendszerek

A névvel ellátott háttérrendszer a következő szintaxissal van definiálva:

\k<név>

vagy:

\k'név'

ahol a név a reguláris kifejezésmintában definiált rögzítési csoport neve. Ha a név nincs definiálva a reguláris kifejezés mintájában, elemzési hiba lép fel, és a reguláris kifejezésmotor egy ArgumentException.

Az alábbi példa egy sztringben található dupla szókarakterekre mutat. Egy reguláris kifejezést határoz meg, (?<char>\w)\k<char>amely a következő elemekből áll.

Elem Leírás
(?<char>\w) Egy szó karakterének egyeztetése és hozzárendelése egy rögzített csoporthoz.char
\k<char> Egyezzen meg a rögzítési csoport értékével char megegyező következő karakternek.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<char>\w)\k<char>";
      string input = "trellis llama webbing dresser swagger";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found '{0}' at position {1}.",
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'll' at position 3.
//       Found 'll' at position 8.
//       Found 'bb' at position 16.
//       Found 'ss' at position 25.
//       Found 'gg' at position 33.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<char>\w)\k<char>"
        Dim input As String = "trellis llama webbing dresser swagger"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found '{0}' at position {1}.", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found 'll' at position 3.
'       Found 'll' at position 8.
'       Found 'bb' at position 16.
'       Found 'ss' at position 25.
'       Found 'gg' at position 33.

Elnevezett numerikus háttérrendszerek

A névvel \kellátott elnevezett háttérrendszerben a név egy szám sztring-ábrázolása is lehet. Az alábbi példa például a reguláris kifejezéssel (?<2>\w)\k<2> keres dupla szó karaktereket egy sztringben. Ebben az esetben a példa egy kifejezetten "2" nevű rögzítési csoportot határoz meg, és a háttérrendszer neve ennek megfelelően "2".

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<2>\w)\k<2>";
      string input = "trellis llama webbing dresser swagger";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found '{0}' at position {1}.",
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'll' at position 3.
//       Found 'll' at position 8.
//       Found 'bb' at position 16.
//       Found 'ss' at position 25.
//       Found 'gg' at position 33.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<2>\w)\k<2>"
        Dim input As String = "trellis llama webbing dresser swagger"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found '{0}' at position {1}.", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found 'll' at position 3.
'       Found 'll' at position 8.
'       Found 'bb' at position 16.
'       Found 'ss' at position 25.
'       Found 'gg' at position 33.

Ha a név egy szám sztringképe, és egyetlen rögzítési csoport sem rendelkezik ezzel a névvel,\k< a név> megegyezik a háttérszámmal\, ahol a szám a rögzítés sorszáma. Az alábbi példában egyetlen rögzítési csoport van elnevezve char. A háttérszerkezet a következőként \k<1>hivatkozik rá: . Ahogy a példa kimenete is mutatja, a hívás Regex.IsMatch sikeres lesz, mert char ez az első rögzítési csoport.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Regex.IsMatch("aa", @"(?<char>\w)\k<1>"));
      // Displays "True".
   }
}

Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Console.WriteLine(Regex.IsMatch("aa", "(?<char>\w)\k<1>"))
        ' Displays "True".
    End Sub
End Module

Ha azonban a név egy szám sztringképe, és az adott pozícióban lévő rögzítési csoporthoz explicit módon numerikus nevet rendeltek, a reguláris kifejezéselemző nem tudja azonosítani a rögzítési csoportot a sorszáma alapján. Ehelyett egy ArgumentException. Az alábbi példában az egyetlen rögzítési csoport neve "2". Mivel a \k szerkezet egy "1" nevű háttérrendszer definiálására szolgál, a reguláris kifejezéselemző nem tudja azonosítani az első rögzítési csoportot, és kivételt jelez.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Regex.IsMatch("aa", @"(?<2>\w)\k<1>"));
      // Throws an ArgumentException.
   }
}

Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Console.WriteLine(Regex.IsMatch("aa", "(?<2>\w)\k<1>"))
        ' Throws an ArgumentException.
    End Sub
End Module

Milyen háttérrendszerek egyeznek?

A háttérrendszer egy csoport legújabb definíciójára hivatkozik (a definíciót a balról jobbra való egyeztetéskor a legközelibb). Ha egy csoport több rögzítést végez, a háttérrendszer a legutóbbi rögzítésre hivatkozik.

Az alábbi példa egy reguláris kifejezésmintát tartalmaz, (?<1>a)(?<1>\1b)*amely újradefiniálja a \1 nevű csoportot. Az alábbi táblázat a reguláris kifejezés minden mintáját ismerteti.

Minta Leírás
(?<1>a) Egyezzen az "a" karakterrel, és rendelje hozzá az eredményt az elnevezett 1rögzítési csoporthoz.
(?<1>\1b)* Egyezzen a "b" névvel elnevezett 1 csoport nulla vagy több előfordulásával, és rendelje hozzá az eredményt a névvel ellátott 1rögzítési csoporthoz.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<1>a)(?<1>\1b)*";
      string input = "aababb";
      foreach (Match match in Regex.Matches(input, pattern))
      {
         Console.WriteLine("Match: " + match.Value);
         foreach (Group group in match.Groups)
            Console.WriteLine("   Group: " + group.Value);
      }
   }
}
// The example displays the following output:
//          Group: aababb
//          Group: abb
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<1>a)(?<1>\1b)*"
        Dim input As String = "aababb"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Match: " + match.Value)
            For Each group As Group In match.Groups
                Console.WriteLIne("   Group: " + group.Value)
            Next
        Next
    End Sub
End Module
' The example display the following output:
'          Group: aababb
'          Group: abb

A reguláris kifejezés és a bemeneti sztring ("aababb") összehasonlítása során a reguláris kifejezésmotor a következő műveleteket hajtja végre:

  1. A sztring elején kezdődik, és sikeresen megegyezik az "a" kifejezéssel (?<1>a). A csoport értéke 1 most "a".

  2. A második karakterre lép, és sikeresen megfelel az "ab" sztringnek az "ab" kifejezéssel vagy az "ab" kifejezéssel \1b. Ezután hozzárendeli az "ab" eredményt a következőhöz: "ab \1".

  3. A negyedik karakterre lép. A kifejezésnek (?<1>\1b)* nullával vagy több alkalommal kell egyeznie, így sikeresen megfelel az "abb" sztringnek a kifejezéssel \1b. Az "abb" eredményt rendeli vissza a következőhöz \1: "abb".

Ebben a példában * egy hurkos kvantitáló – a rendszer többször kiértékeli, amíg a reguláris kifejezésmotor nem tud megegyezni az általa definiált mintával. A hurkos kvantátorok nem törlik a csoportdefiníciókat.

Ha egy csoport nem rögzítette az alsztringeket, az adott csoporthoz tartozó háttérrendszer nincs definiálva, és soha nem egyezik. Ezt a reguláris kifejezésminta \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\bszemlélteti, amely a következőképpen van definiálva:

Minta Leírás
\b Kezdje el az egyezést egy szóhatáron.
(\p{Lu}{2}) Egyezzen két nagybetűvel. Ez az első rögzítési csoport.
(\d{2})? Egyezik két tizedesjegy nullával vagy egy előfordulásával. Ez a második rögzítési csoport.
(\p{Lu}{2}) Egyezzen két nagybetűvel. Ez a harmadik rögzítési csoport.
\b Egy szóhatáron fejezd be az egyezést.

Egy bemeneti sztring akkor is megfelelhet ennek a reguláris kifejezésnek, ha a második rögzítési csoport által definiált két tizedesjegy nincs jelen. Az alábbi példa azt mutatja, hogy bár az egyezés sikeres, egy üres rögzítési csoport található két sikeres rögzítési csoport között.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b";
      string[] inputs = { "AA22ZZ", "AABB" };
      foreach (string input in inputs)
      {
         Match match = Regex.Match(input, pattern);
         if (match.Success)
         {
            Console.WriteLine("Match in {0}: {1}", input, match.Value);
            if (match.Groups.Count > 1)
            {
               for (int ctr = 1; ctr <= match.Groups.Count - 1; ctr++)
               {
                  if (match.Groups[ctr].Success)
                     Console.WriteLine("Group {0}: {1}",
                                       ctr, match.Groups[ctr].Value);
                  else
                     Console.WriteLine("Group {0}: <no match>", ctr);
               }
            }
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       Match in AA22ZZ: AA22ZZ
//       Group 1: AA
//       Group 2: 22
//       Group 3: ZZ
//
//       Match in AABB: AABB
//       Group 1: AA
//       Group 2: <no match>
//       Group 3: BB
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b"
        Dim inputs() As String = {"AA22ZZ", "AABB"}
        For Each input As String In inputs
            Dim match As Match = Regex.Match(input, pattern)
            If match.Success Then
                Console.WriteLine("Match in {0}: {1}", input, match.Value)
                If match.Groups.Count > 1 Then
                    For ctr As Integer = 1 To match.Groups.Count - 1
                        If match.Groups(ctr).Success Then
                            Console.WriteLine("Group {0}: {1}", _
                                              ctr, match.Groups(ctr).Value)
                        Else
                            Console.WriteLine("Group {0}: <no match>", ctr)
                        End If
                    Next
                End If
            End If
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       Match in AA22ZZ: AA22ZZ
'       Group 1: AA
'       Group 2: 22
'       Group 3: ZZ
'       
'       Match in AABB: AABB
'       Group 1: AA
'       Group 2: <no match>
'       Group 3: BB

Lásd még