Normal İfadelerdeki Yeniden Başvuru Yapıları

Geri başvurular, bir dize içinde yinelenen bir karakteri veya alt dizeyi tanımlamak için kullanışlı bir yol sağlar. Örneğin, giriş dizesi rastgele bir alt dizenin birden çok tekrarını içeriyorsa, ilk oluşumu bir yakalama grubuyla eşleştirebilir ve sonra alt dizenin sonraki oluşumlarını eşleştirmek için bir geri başvuru kullanabilirsiniz.

Not

Değiştirme dizelerindeki adlandırılmış ve numaralandırılmış yakalama gruplarına başvurmak için ayrı bir söz dizimi kullanılır. Daha fazla bilgi için bkz . Değiştirmeler.

.NET, numaralandırılmış ve adlandırılmış yakalama gruplarına başvurmak için ayrı dil öğeleri tanımlar. Grupları yakalama hakkında daha fazla bilgi için bkz . Gruplandırma Yapıları.

Numaralandırılmış Geri Başvurular

Numaralandırılmış geri başvuru aşağıdaki söz dizimini kullanır:

\Numarası

burada sayı , yakalama grubunun normal ifadedeki sıralı konumudur. Örneğin, \4 dördüncü yakalama grubunun içeriğiyle eşleşir. Sayı normal ifade deseninde tanımlanmamışsa bir ayrıştırma hatası oluşur ve normal ifade altyapısı bir ArgumentExceptionoluşturur. Örneğin, normal ifade \b(\w+)\s\1 geçerli (\w+) çünkü ifadedeki ilk ve tek yakalama grubudur. Öte yandan, \b(\w+)\s\2 geçersizdir ve numaralı \2yakalama grubu olmadığından bağımsız değişken özel durumu oluşturur. Buna ek olarak, sayı belirli bir sıra konumundaki bir yakalama grubunu tanımlarsa, ancak bu yakalama grubuna sıra konumundan farklı bir sayısal ad atanmışsa, normal ifade ayrıştırıcısı da bir ArgumentExceptionoluşturur.

Aynı gösterimi kullanan sekizli kaçış kodları (gibi \16) ve \sayı geri başvuruları arasındaki belirsizliğe dikkat edin. Bu belirsizlik aşağıdaki gibi çözülür:

  • aracılığıyla \9 ifadeler \1 her zaman geri başvuru olarak yorumlanır ve sekizli kodlar olarak yorumlanmaz.

  • Çok boyutlu bir ifadenin ilk basamak değeri 8 veya 9 ise (veya gibi \80\91), ifade değişmez değer olarak yorumlanır.

  • ve üzeri ifadeler \10 , bu sayıya karşılık gelen bir geri başvuru varsa geri başvuru olarak kabul edilir; aksi takdirde, sekizli kod olarak yorumlanırlar.

  • Normal ifade tanımlanmamış bir grup numarasına geri başvuru içeriyorsa, ayrıştırma hatası oluşur ve normal ifade altyapısı bir ArgumentExceptionoluşturur.

Belirsizlik bir sorunsa, kesin olmayan ve sekizli karakter kodlarıyla karıştırılamayan ad> gösterimini kullanabilirsiniz\k<. Benzer şekilde, gibi \xdd onaltılık kodlar kesin değildir ve geri başvurularla karıştırılamaz.

Aşağıdaki örnek, bir dizedeki çift sözcük karakterlerini bulur. Aşağıdaki öğelerden oluşan bir normal ifade (\w)\1tanımlar.

Öğe Açıklama
(\w) Bir sözcük karakterini eşleştirin ve ilk yakalama grubuna atayın.
\1 İlk yakalama grubunun değeriyle aynı olan sonraki karakteri eşleştirin.
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.

Adlandırılmış Geri Başvurular

Adlandırılmış geri başvuru aşağıdaki söz dizimi kullanılarak tanımlanır:

\k<Adı>

veya:

\k'Adı'

burada ad , normal ifade deseninde tanımlanan bir yakalama grubunun adıdır. Ad normal ifade deseninde tanımlanmamışsa bir ayrıştırma hatası oluşur ve normal ifade altyapısı bir ArgumentExceptionoluşturur.

Aşağıdaki örnek, bir dizedeki çift sözcük karakterlerini bulur. Aşağıdaki öğelerden oluşan bir normal ifade (?<char>\w)\k<char>tanımlar.

Öğe Açıklama
(?<char>\w) Bir sözcük karakterini eşleştirin ve adlı bir yakalama grubuna atayın char.
\k<char> Yakalama grubunun değeriyle aynı olan sonraki karakterle char eşleş.
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.

Adlandırılmış sayısal geri başvurular

ile \kadlandırılmış bir geri başvuruda ad, bir sayının dize gösterimi de olabilir. Örneğin, aşağıdaki örnek, bir dizedeki çift sözcük karakterlerini bulmak için normal ifadeyi (?<2>\w)\k<2> kullanır. Bu durumda, örnek açıkça "2" adlı bir yakalama grubu tanımlar ve geri başvuru karşılık gelen "2" olarak adlandırılır.

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.

Ad bir sayının dize gösterimiyse ve hiçbir yakalama grubu bu ada sahip değilse,\k< ad> geri başvuru\ numarasıyla aynıdır; burada sayı, yakalamanın sıralı konumudur. Aşağıdaki örnekte adlı chartek bir yakalama grubu vardır. backreference yapısı bunu olarak \k<1>ifade eder. Örnekteki çıktıda gösterildiği gibi, ilk yakalama grubu olduğu char için Regex.IsMatch çağrısı başarılı olur.

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

Ancak, ad bir sayının dize gösterimiyse ve bu konumdaki yakalama grubuna açıkça bir sayısal ad atanmışsa, normal ifade ayrıştırıcısı yakalama grubunu sıralı konumuna göre tanımlayamaz. Bunun yerine, bir ArgumentExceptionoluşturur. Aşağıdaki örnekteki tek yakalama grubu "2" olarak adlandırılır. \k Yapısı "1" adlı bir geri başvuru tanımlamak için kullanıldığından, normal ifade ayrıştırıcısı ilk yakalama grubunu tanımlayamaz ve bir özel durum oluşturur.

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

Hangi Geri Başvurular Eşleşmektedir?

Geri başvuru, bir grubun en son tanımına (soldan sağa eşleştirildiğinde en hemen sola doğru olan tanım) başvurur. Bir grup birden çok yakalama yaptığında, geri başvuru en son yakalamaya başvurur.

Aşağıdaki örnek, (?<1>a)(?<1>\1b)*\1 adlı grubu yeniden tanımlayan bir normal ifade deseni içerir. Aşağıdaki tabloda normal ifadedeki her desen açıklanmaktadır.

Desen Açıklama
(?<1>a) "a" karakterini eşleştirin ve sonucu adlı 1yakalama grubuna atayın.
(?<1>\1b)* Adlı 1 grubun sıfır veya daha fazla örneğini bir "b" ile eşleştirin ve sonucu adlı yakalama grubuna atayın 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

Normal ifadeyi giriş dizesi ("aababb") ile karşılaştırırken, normal ifade altyapısı aşağıdaki işlemleri gerçekleştirir:

  1. Dizenin başında başlar ve "a" ifadesini ifadesiyle (?<1>a)başarıyla eşleştirir. Grubun değeri 1 artık "a" olur.

  2. İkinci karaktere ilerler ve "ab" dizesini , veya "ab" ifadesiyle \1bbaşarıyla eşleştirir. Ardından "ab" sonucunu öğesine \1atar.

  3. Dördüncü karaktere ilerler. İfade (?<1>\1b)* sıfır veya daha fazla kez eşleştirilecek, bu nedenle "abb" dizesini ifadesiyle \1bbaşarıyla eşleştirir. "abb" sonucunu öğesine \1geri atar.

Bu örnekte, * döngü niceleyicidir; normal ifade altyapısı tanımladığı desenle eşleşmeyene kadar tekrar tekrar değerlendirilir. Döngü niceleyicileri grup tanımlarını temizlemez.

Bir grup herhangi bir alt dize yakalamadıysa, bu gruba yapılan geri başvuru tanımlanmamıştır ve hiçbir zaman eşleşmez. Bu, aşağıdaki gibi tanımlanan normal ifade deseni \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\bile gösterilmiştir:

Desen Açıklama
\b Eşleşmeyi bir sözcük sınırında başlatın.
(\p{Lu}{2}) İki büyük harf eşleştirin. Bu ilk yakalama grubudur.
(\d{2})? İki ondalık basamağın sıfır veya bir oluşumunu eşleştirin. Bu ikinci yakalama grubudur.
(\p{Lu}{2}) İki büyük harf eşleştirin. Bu, üçüncü yakalama grubudur.
\b Eşleşmeyi bir sözcük sınırında sonlandırın.

giriş dizesi, ikinci yakalama grubu tarafından tanımlanan iki ondalık basamak mevcut olmasa bile bu normal ifadeyle eşleşebilir. Aşağıdaki örnekte, eşleşme başarılı olsa da iki başarılı yakalama grubu arasında boş bir yakalama grubu bulunduğu gösterilmektedir.

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

Ayrıca bkz.