Konstruksi Referensi Balik dalam Ekspresi Reguler

Referensi balik menyediakan cara yang nyaman untuk mengidentifikasi karakter berulang atau substring dalam string. Misalnya, jika string input berisi beberapa kejadian substring arbitrer, Anda dapat mencocokkan kejadian pertama dengan grup pengambilan, lalu menggunakan referensi balik untuk mencocokkan kejadian substring berikutnya.

Catatan

Sintaks terpisah digunakan untuk merujuk ke grup pengambilan bernama dan bernomor dalam string pengganti. Untuk informasi selengkapnya, lihat Substitusi.

.NET menetapkan elemen bahasa terpisah untuk merujuk ke grup pengambilan bernomor dan bernama. Untuk informasi selengkapnya tentang menangkap grup, lihat Konstruksi Pengelompokan.

Referensi Balik Bernomor

Referensi balik bernomor menggunakan sintaks berikut:

\number

menandakan angka adalah posisi ordinal grup pengambilan dalam ekspresi reguler. Misalnya, \4 cocok dengan konten grup pengambilan keempat. Jika angka tidak ditentukan dalam pola ekspresi reguler, kesalahan penguraian terjadi, dan mesin ekspresi reguler membuat ArgumentException. Misalnya, ekspresi \b(\w+)\s\1 reguler valid, karena (\w+) merupakan grup pertama dan hanya menangkap dalam ekspresi. Di sisi lain, \b(\w+)\s\2 tidak valid dan membuat pengecualian argumen, karena tidak ada pengambilan grup bernomor \2. Selain itu, jika angka mengidentifikasi grup pengambilan dalam posisi ordinal tertentu, tetapi grup pengambilan tersebut telah diberi nama numerik yang berbeda dari posisi ordinalnya, pengurai ekspresi reguler juga membuat ArgumentException.

Perhatikan ambiguitas antara kode lolos oktal (seperti \16) dan \referensi balik angka yang menggunakan notasi yang sama. Ambiguitas ini diselesaikan sebagai berikut:

  • Ekspresi \1 melalui \9 selalu ditafsirkan sebagai referensi balik, dan bukan sebagai kode oktal.

  • Jika digit pertama ekspresi multidigit adalah 8 atau 9 (seperti \80 atau \91), ekspresi sebagai ditafsirkan sebagai harfiah.

  • Ekspresi dari \10 dan yang lebih besar dianggap sebagai referensi balik jika ada referensi balik yang sesuai dengan angka tersebut; jika tidak, ekspresi tersebut ditafsirkan sebagai kode oktal.

  • Jika ekspresi reguler berisi referensi balik ke nomor grup yang tidak terdefinisi, kesalahan penguraian terjadi, dan mesin ekspresi reguler membuat ArgumentException.

Jika ambiguitas adalah masalah, Anda dapat menggunakan notasi \k<nama>, yang tidak ambigu dan tidak dapat dikacaukan dengan kode karakter oktal. Demikian pula, kode heksadesimal seperti \xdd tidak ambigu dan tidak dapat dikacaukan dengan referensi balik.

Contoh berikut menemukan karakter kata ganda dalam string. Ia menentukan ekspresi reguler, (\w)\1, yang terdiri dari elemen-elemen berikut.

Elemen Deskripsi
(\w) Cocokkan karakter kata dan tetapkan ke grup pengambilan pertama.
\1 Cocokkan karakter berikutnya yang sama dengan nilai grup pengambilan pertama.
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.

Referensi balik bernama

Referensi balik bernama ditentukan dengan menggunakan sintaks berikut:

\k<nama>

atau:

\k'nama'

menandakan nama adalah nama grup pengambilan yang ditentukan dalam pola ekspresi reguler. Jika angka tidak ditentukan dalam pola ekspresi reguler, kesalahan penguraian terjadi, dan mesin ekspresi reguler membuat ArgumentException.

Contoh berikut menemukan karakter kata ganda dalam string. Ia menentukan ekspresi reguler, (?<char>\w)\k<char>, yang terdiri dari elemen-elemen berikut.

Elemen Deskripsi
(?<char>\w) Cocokkan karakter kata dan tetapkan ke grup pengambilan pertama char.
\k<char> Cocokkan karakter berikutnya yang sama dengan nilai char grup pengambilan pertama.
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.

Referensi balik numerik bernama

Dalam referensi balik bernama dengan \k, nama juga dapat menjadi representasi string dari angka. Misalnya, contoh berikut menggunakan ekspresi (?<2>\w)\k<2> reguler untuk menemukan karakter kata ganda dalam string. Dalam hal ini, contoh menentukan grup pengambilan yang secara eksplisit bernama "2", dan referensi balik secara sesuai bernama "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.

Jika nama adalah representasi string dari angka, dan tidak ada grup pengambilan yang memiliki nama tersebut, \k<nama> sama dengan \angka referensi balik, yang menandakan angka sebagai posisi ordinal pengambilan. Dalam contoh berikut, ada satu grup pengambilan bernama char. Konstruksi referensi balik menyebutnya sebagai \k<1>. Seperti yang ditunjukkan oleh output dari contoh, panggilan ke Regex.IsMatch berhasil karena char merupakan grup pengambilan pertama.

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

Namun, jika nama adalah representasi string dari angka dan grup pengambilan dalam posisi tersebut telah secara eksplisit menetapkan nama numerik, pengurai ekspresi reguler tidak dapat mengidentifikasi grup pengambilan dengan posisi ordinalnya. Sebaliknya, ia membuat ArgumentException. Satu-satunya grup pengambilan dalam contoh berikut diberi nama "2". Karena \k konstruksi digunakan untuk menentukan referensi balik bernama "1", pengurai ekspresi reguler tidak dapat mengidentifikasi grup pengambilan pertama dan membuat pengecualian.

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

Apa Kecocokan Referensi Balik

Referensi balik mengacu pada definisi terbaru dari suatu grup (definisi paling segera ke kiri, ketika cocok kiri ke kanan). Ketika grup membuat beberapa pengambilan, referensi balik mengacu pada pengambilan terbaru.

Contoh berikut mencakup pola ekspresi reguler, (?<1>a)(?<1>\1b)*, yang menentukan ulang grup bernama \1. Tabel berikut menjelaskan setiap pola dalam ekspresi reguler.

Pola Deskripsi
(?<1>a) Cocokkan karakter "a" dan tetapkan hasilnya ke grup pengambilan bernama 1.
(?<1>\1b)* Cocokkan nol atau lebih kejadian grup bernama 1 bersama dengan "b", dan tetapkan hasilnya ke grup pengambilan bernama 1.
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

Dalam membandingkan ekspresi reguler dengan string input ("aababb"), mesin ekspresi reguler melakukan operasi berikut:

  1. Ini dimulai di awal string, dan berhasil mencocokkan "a" dengan ekspresi (?<1>a). Nilai 1 grup sekarang adalah "a".

  2. Ini maju ke karakter kedua, dan berhasil mencocokkan string "ab" dengan ekspresi \1b, atau "ab". Kemudian menetapkan hasilnya, "ab" ke \1.

  3. Ini maju ke karakter keempat. Ekspresi (?<1>\1b)* akan dicocokkan nol atau lebih kali, sehingga berhasil mencocokkan string "abb" dengan ekspresi \1b. Ini menetapkan hasilnya, "abb", kembali ke \1.

Dalam contoh ini, * adalah pembilang perulangan -- dievaluasi berulang kali sampai mesin ekspresi reguler tidak dapat mencocokkan pola yang ditentukannya. Pembilang perulangan tidak menghapus definisi grup.

Jika grup belum menangkap substring apa pun, referensi balik ke grup tersebut tidak terdefinisi dan tidak pernah cocok. Ini diilustrasikan oleh pola \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\bekspresi reguler, yang ditentukan sebagai berikut:

Pola Deskripsi
\b Mulai kecocokan pada batas kata.
(\p{Lu}{2}) Cocokkan dua huruf besar. Ini adalah grup penangkapan pertama.
(\d{2})? Cocokkan nol atau satu kejadian dari dua digit desimal. Ini adalah grup pengambilan kedua.
(\p{Lu}{2}) Cocokkan dua huruf besar. Ini adalah grup pengambilan ketiga.
\b Akhiri pencocokan pada batas kata.

String input dapat cocok dengan ekspresi reguler ini bahkan jika dua digit desimal yang ditentukan oleh grup pengambilan kedua tidak ada. Contoh berikut menunjukkan bahwa meskipun kecocokan berhasil, grup pengambilan kosong ditemukan di antara dua grup pengambilan yang berhasil.

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

Lihat juga