Rückverweiskonstrukte
Rückverweise bieten eine zweckmäßige Möglichkeit, ein wiederholtes Zeichen oder eine Teilzeichenfolge innerhalb einer Zeichenfolge zu identifizieren. Wenn die Eingabezeichenfolge beispielsweise mehrere Vorkommen einer beliebigen Teilzeichenfolge enthält, können Sie das erste Vorkommen mit einer Erfassungsgruppe abgleichen und anschließend die nachfolgenden Vorkommen der Teilzeichenfolge mithilfe eines Rückverweises abgleichen.
Hinweis |
---|
Eine separate Syntax wird verwendet, um auf benannte und nummerierte Erfassungsgruppen in Ersetzungszeichenfolgen zu verweisen.Weitere Informationen finden Sie unter Ersetzungen. |
.NET Framework definiert separate Sprachelemente, um auf nummerierte und benannte Erfassungsgruppen zu verweisen. Weitere Informationen zu Erfassungsgruppen finden Sie unter Gruppierungskonstrukte.
Nummerierte Rückverweise
Ein nummerierter Rückverweis verwendet die folgende Syntax:
\number
wobei Nummer die Ordnungsposition der Erfassungsgruppe im regulären Ausdruck ist. Beispielsweise stimmt \4 mit dem Inhalt der vierten Erfassungsgruppe überein. Wenn Zahl nicht im Muster eines regulären Ausdrucks definiert wurde, tritt ein Analysefehler auf, und das Modul für reguläre Ausdrücke löst eine ArgumentException aus. Der reguläre Ausdruck \b(\w+)\s\1 ist z. B. gültig, da (\w+) die erste und einzige Erfassungsgruppe im Ausdruck ist. Andererseits ist \b(\w+)\s\2 ungültig und löst eine Argumentausnahme aus, da keine Erfassungsgruppe mit der Nummer \2 vorhanden ist.
Beachten Sie die Zweideutigkeit bei Oktalescapecodes (wie \16) und \Zahlen-Rückverweisen mit der gleichen Notation. Diese Mehrdeutigkeit wird folgendermaßen aufgelöst:
Die Ausdrücke "\1" bis "\9" werden immer als Rückverweise und nicht als oktale Codes interpretiert.
Wenn die erste Ziffer eines multidigit-Ausdrucks 8 oder 9 ist (z. B. \80 oder \91), wird der Ausdruck als Literal interpretiert.
Ausdrücke von \10 und größer werden als Rückverweise betrachtet, wenn es einen Rückverweis gibt, der dieser Zahl entspricht; andernfalls werden sie als oktale Codes interpretiert.
Enthält ein regulärer Ausdruck einen Rückverweis auf eine nicht definierte Gruppennummer, tritt ein Analysefehler auf, und das Modul für reguläre Ausdrücke löst eine ArgumentException aus.
Wenn die Mehrdeutigkeit ein Problem ist, können Sie die \k<Name>-Notation verwenden, die unzweideutig ist und nicht mit oktalen Zeichencodes verwechselt werden kann. Auf ähnliche Weise sind hexadezimale Codes wie \xdd unzweideutig und können nicht mit Rückverweisen verwechselt werden.
Im folgenden Beispiel befinden sich doppelte Wortzeichen in einer Zeichenfolge. Ein regulärer Ausdruck ((\w)\1) wird definiert, der aus den folgenden Elementen besteht.
Element |
Beschreibungen |
---|---|
(\w) |
Entspricht einem Wortzeichen und weist es der ersten Erfassungsgruppe zu. |
\1 |
Entspricht dem nächsten Zeichen, das mit dem Wert der ersten Erfassungsgruppe identisch ist. |
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.
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.
Benannte Rückverweise
Ein benannter Rückverweis wird mit der folgenden Syntax definiert:
\k<name>
oder:
\k'name'
wobei Name der Name einer Erfassungsgruppe ist, die im Muster des regulären Ausdrucks definiert ist. Wenn Name nicht im Muster eines regulären Ausdrucks definiert wurde, tritt ein Analysefehler auf, und das Modul für reguläre Ausdrücke löst eine ArgumentException aus.
Im folgenden Beispiel befinden sich doppelte Wortzeichen in einer Zeichenfolge. Ein regulärer Ausdruck ((?<char>\w)\k<char>) wird definiert, der aus den folgenden Elementen besteht.
Element |
Beschreibungen |
---|---|
(?<char>\w) |
Entspricht einem Wortzeichen und weist es einer Erfassungsgruppe mit dem Namen char zu. |
\k<char> |
Entspricht dem nächsten Zeichen, das mit dem Wert der char-Erfassungsgruppe identisch ist. |
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.
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.
Name kann auch die Zeichenfolgendarstellung einer Zahl sein. Im folgenden Beispiel wird der reguläre Ausdruck (?<2>\w)\k<2> verwendet, um doppelte Wortzeichen in einer Zeichenfolge zu finden.
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.
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.
Übereinstimmende Rückverweise
Ein Rückverweis bezieht sich immer auf die aktuellste Definition einer Gruppe (die Definition, die bei der Suche von links nach rechts am weitesten links steht). Wenn durch eine Gruppe mehrere Übereinstimmungen gefunden werden, bezieht sich ein Rückverweis auf die aktuellste Erfassung.
Das folgende Beispiel enthält ein Muster eines regulären Ausdrucks, (?<1>a)(?<1>\1b)*, das die benannte \1-Gruppe neu definiert. In der folgenden Tabelle wird jedes Muster im regulären Ausdruck beschrieben.
Muster |
Beschreibungen |
---|---|
(?<1>a) |
Entspricht dem Zeichen "a" und weist das Ergebnis der Erfassungsgruppe mit der Bezeichnung 1 zu. |
(?<1>\1b)* |
Vergleichen Sie 0 oder 1 Vorkommen der Gruppe mit dem Namen 1 zusammen mit einem "b", und weisen Sie das Ergebnis der Erfassungsgruppe mit dem Namen 1 zu. |
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
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
Beim Vergleich des regulären Ausdrucks mit der Eingabezeichenfolge ("aababb") führt das Modul für reguläre Ausdrücke die folgenden Vorgänge aus:
Begonnen wird am Anfang der Zeichenfolge, und "a" wird mit dem Ausdruck (?<1>a) abgeglichen. Der Wert der 1-Gruppe ist nun ein "a".
Es wird zum zweiten Zeichen gewechselt, und die Zeichenfolge "ab" wird erfolgreich mit dem Ausdruck \1b oder "ab" abgeglichen. Anschließend wird das Ergebnis ("ab)" \1 zugewiesen.
Es wird zum vierten Zeichen gewechselt. Der Ausdruck (?<1>\1b) muss nullmal oder mehrfach abgeglichen werden, damit er der Zeichenfolge "abb" mit dem Ausdruck \1b entspricht. Das Ergebnis ("abb") wird wieder \1 zugewiesen.
In diesem Beispiel ist * ein Schleifenquantifizierer – er wird laufend ausgewertet, bis das Modul für reguläre Ausdrücke keine Entsprechung für das Muster finden kann, das es definiert. Quantifizierer, die in Schleifen durchlaufen werden, löschen keine Gruppendefinitionen.
Wurden durch eine Gruppe keine Teilzeichenfolgen gefunden, ist der Rückverweis auf diese Gruppe nicht definiert und führt niemals zu einem Suchergebnis. Dies wird durch das Muster eines regulären Ausdrucks, \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b, veranschaulicht, der folgendermaßen definiert wird:
Muster |
Beschreibungen |
---|---|
\b |
Beginnt den Vergleich an einer Wortgrenze. |
(\p{Lu}{2}) |
Entspricht zwei Großbuchstaben. Dies ist die erste Erfassungsgruppe. |
(\d{2})? |
Entspricht null oder einem Vorkommen von zwei Dezimalstellen. Dies ist die zweite Erfassungsgruppe. |
(\p{Lu}{2}) |
Entspricht zwei Großbuchstaben. Dies ist die dritte Erfassungsgruppe. |
\b |
Beendet den Vergleich an einer Wortgrenze. |
Eine Eingabezeichenfolge kann mit diesem regulären Ausdruck übereinstimmen, auch wenn die zwei Dezimalstellen, die von der zweiten Erfassungsgruppe definiert werden, nicht vorhanden sind. Das folgende Beispiel zeigt, dass trotz einer Übereinstimmung eine leere Erfassungsgruppe zwischen zwei erfolgreichen Erfassungsgruppen gefunden wird.
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
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