Beispiel für reguläre Ausdrücke: Suchen nach HREFs

Im folgenden Beispiel wird eine Eingabezeichenfolge durchsucht, und es werden alle href="..."-Werte und ihre Positionen in der Zeichenfolge angezeigt.

Warnung

Übergeben Sie ein Timeout, wenn Sie System.Text.RegularExpressions zum Verarbeiten nicht vertrauenswürdiger Eingaben verwenden. Böswillige Benutzer können Eingaben für RegularExpressions bereitstellen, um einen Denial-of-Service-Angriff durchzuführen. ASP.NET Core-Framework-APIs, die RegularExpressions verwenden, übergeben ein Timeout.

Das Regex-Objekt

Da die DumpHRefs-Methode vom Benutzercode aus mehrmals aufgerufen werden kann, verwendet sie die static (Shared in Visual Basic) Regex.Match(String, String, RegexOptions)-Methode. Dies ermöglicht der Engine für reguläre Ausdrücke, den regulären Ausdruck zwischenzuspeichern, und vermeidet den Mehraufwand, bei jedem Aufruf der Methode ein neues Regex-Objekt zu instanziieren. Ein Match-Objekt wird anschließend verwendet, um alle Übereinstimmungen in der Zeichenfolge zu durchlaufen.

private static void DumpHRefs(string inputString)
{
    string hrefPattern = @"href\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>[^>\s]+))";

    try
    {
        Match regexMatch = Regex.Match(inputString, hrefPattern,
                                       RegexOptions.IgnoreCase | RegexOptions.Compiled,
                                       TimeSpan.FromSeconds(1));
        while (regexMatch.Success)
        {
            Console.WriteLine($"Found href {regexMatch.Groups[1]} at {regexMatch.Groups[1].Index}");
            regexMatch = regexMatch.NextMatch();
        }
    }
    catch (RegexMatchTimeoutException)
    {
        Console.WriteLine("The matching operation timed out.");
    }
}
Private Sub DumpHRefs(inputString As String)
    Dim hrefPattern As String = "href\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>[^>\s]+))"

    Try
        Dim regexMatch = Regex.Match(inputString, hrefPattern,
                                     RegexOptions.IgnoreCase Or RegexOptions.Compiled,
                                     TimeSpan.FromSeconds(1))
        Do While regexMatch.Success
            Console.WriteLine($"Found href {regexMatch.Groups(1)} at {regexMatch.Groups(1).Index}.")
            regexMatch = regexMatch.NextMatch()
        Loop
    Catch e As RegexMatchTimeoutException
        Console.WriteLine("The matching operation timed out.")
    End Try
End Sub

Im folgenden Beispiel wird ein Aufruf der DumpHRefs-Methode veranschaulicht.

public static void Main()
{
    string inputString = "My favorite web sites include:</P>" +
                         "<A HREF=\"https://learn.microsoft.com/en-us/dotnet/\">" +
                         ".NET Documentation</A></P>" +
                         "<A HREF=\"http://www.microsoft.com\">" +
                         "Microsoft Corporation Home Page</A></P>" +
                         "<A HREF=\"https://devblogs.microsoft.com/dotnet/\">" +
                         ".NET Blog</A></P>";
    DumpHRefs(inputString);
}
// The example displays the following output:
//       Found href https://learn.microsoft.com/dotnet/ at 43
//       Found href http://www.microsoft.com at 114
//       Found href https://devblogs.microsoft.com/dotnet/ at 188
Public Sub Main()
    Dim inputString As String = "My favorite web sites include:</P>" &
                                "<A HREF=""https://learn.microsoft.com/en-us/dotnet/"">" &
                                ".NET Documentation</A></P>" &
                                "<A HREF=""http://www.microsoft.com"">" &
                                "Microsoft Corporation Home Page</A></P>" &
                                "<A HREF=""https://devblogs.microsoft.com/dotnet/"">" &
                                ".NET Blog</A></P>"
    DumpHRefs(inputString)
End Sub
' The example displays the following output:
'       Found href https://learn.microsoft.com/dotnet/ at 43
'       Found href http://www.microsoft.com at 114
'       Found href https://devblogs.microsoft.com/dotnet/ at 188

Das Muster für reguläre Ausdrücke href\s*=\s*(?:["'](?<1>[^"']*)["']|(?<1>[^>\s]+)) wird entsprechend der folgenden Tabelle interpretiert:

Muster Beschreibung
href Sucht nach der Literalzeichenfolge „href“. Die Groß- und Kleinschreibung wird bei der Übereinstimmung nicht berücksichtigt.
\s* Sucht nach 0 (null) oder mehr Leerzeichen.
= Sucht nach dem Gleichheitszeichen.
\s* Sucht nach 0 (null) oder mehr Leerzeichen.
(?: Starten Sie eine Nicht-Erfassungsgruppe.
["'](?<1>[^"']*)["'] Entspricht einem Anführungszeichen oder Apostroph, gefolgt von einer Erfassungsgruppe, die einem beliebigen anderen Zeichen als einem Anführungszeichen oder Apostroph, gefolgt von einem Anführungszeichen oder einem Apostroph, entspricht. Die Gruppe namens 1 ist in diesem Muster enthalten.
| Boolesches ODER (OR), das entweder dem vorherigen Ausdruck oder dem nächsten Ausdruck entspricht.
(?<1>[^>\s]+) Eine Erfassungsgruppe, die einen negierten Satz verwendet, um jedem andere Zeichen als einem Größer-als-Zeichen oder einem Leerzeichen zu entsprechen. Die Gruppe namens 1 ist in diesem Muster enthalten.
) Beenden Sie die Nicht-Erfassungsgruppe.

Abgleichsergebnisklasse

Die Ergebnisse einer Suche werden in der Match-Klasse gespeichert, die Zugriff auf alle von der Suche extrahierten Teilzeichenfolgen bietet. Die durchsuchte Zeichenfolge und der verwendete reguläre Ausdruck werden ebenfalls gespeichert, sodass die Match.NextMatch-Methode aufgerufen werden kann, um einen weiteren Suchvorgang ab der Stelle auszuführen, an der der letzte Suchvorgang beendet wurde.

Explizit benannte Erfassungen

In herkömmlichen regulären Ausdrücken werden Klammern für die Erfassung automatisch nach der Reihenfolge durchnummeriert. Daraus ergeben sich zwei Probleme. Zum einen muss nach dem Einfügen oder Entfernen von Klammern jeglicher Code, der auf die nummerierten Klammern verweist, der neuen Nummerierung entsprechend umgeschrieben werden. Zweitens werden häufig unterschiedliche Klammerpaare verwendet, um zwei Alternativausdrücke für eine Übereinstimmung zu erhalten. Dadurch wird es schwierig festzustellen, durch welchen der beiden Ausdrücke das Ergebnis zurückgegeben wurde.

Um diesen Schwierigkeiten zu begegnen, unterstützt die Regex-Klasse die (?<name>…)-Syntax zur Erfassung einer Übereinstimmung in einem festgelegten Slot. (Der Slot kann mit einer Zeichenfolge oder einer ganzen Zahl benannt werden; ganze Zahlen können schneller aufgerufen werden.) Damit können alle Suchergebnisse für dieselbe Zeichenfolge an denselben Ort geleitet werden. Im Fall eines Konflikts ist das zuletzt im Slot gespeicherte Suchergebnis gültig. (Eine vollständige Liste mehrerer Übereinstimmungen für einen einzelnen Slot steht jedoch zur Verfügung. Details finden Sie in der Group.Captures-Auflistung.)

Weitere Informationen