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:
\
sayı
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ı \2
yakalama 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)\1
tanı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 \k
adlandı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ı char
tek 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ı 1 yakalama 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:
Dizenin başında başlar ve "a" ifadesini ifadesiyle
(?<1>a)
başarıyla eşleştirir. Grubun değeri1
artık "a" olur.İkinci karaktere ilerler ve "ab" dizesini , veya "ab" ifadesiyle
\1b
başarıyla eşleştirir. Ardından "ab" sonucunu öğesine\1
atar.Dördüncü karaktere ilerler. İfade
(?<1>\1b)*
sıfır veya daha fazla kez eşleştirilecek, bu nedenle "abb" dizesini ifadesiyle\1b
başarıyla eşleştirir. "abb" sonucunu öğesine\1
geri 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})\b
ile 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