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.

Warning

Die uneingeschränkte Verwendung von System.Text.RegularExpressions mit nicht vertrauenswürdigen Eingaben kann Anwendungen Denial-of-Service-Angriffen aussetzen. Lesen Sie bewährte Methoden für reguläre Ausdrücke in .NET, um Anleitungen zur sicheren Verwendung von .NET regulären Ausdrücken mit nicht vertrauenswürdigen Eingaben zu erhalten.

Das Regex-Objekt

Da die DumpHRefs Methode mehrmals aus Benutzercode aufgerufen werden kann, verwendet sie die static (Sharedin Visual Basic)- Regex.Match(String, String, RegexOptions) Methode. Dadurch kann das Modul für reguläre Ausdrücke den regulären Ausdruck zwischenspeichern und verhindert den Aufwand beim Instanziieren eines neuen Regex Objekts bei jedem Aufruf der Methode. Anschließend wird ein Match-Objekt verwendet, mit dem alle Übereinstimmungen in der Zeichenfolge durchlaufen werden.

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 dann 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:

Schema Description
href Entspricht der wörtlichen Zeichenfolge "href". Die Groß- und Kleinschreibung wird bei der Übereinstimmung nicht berücksichtigt.
\s* Sucht nach 0 (null) oder mehr Leerzeichen.
= Ordnen Sie das Gleichheitszeichen zu.
\s* Sucht nach 0 (null) oder mehr Leerzeichen.
(?: Starten Sie eine nicht-kapturierende Gruppe.
["'](?<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 benannte 1 Gruppe ist in diesem Muster enthalten.
| Boolesches ODER, das entweder auf den vorherigen Ausdruck oder den nächsten Ausdruck zutrifft.
(?<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 benannte 1 Gruppe 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 ermöglicht. Es merkt sich auch die gesuchte Zeichenfolge und den verwendeten regulären Ausdruck, sodass sie die Match.NextMatch Methode aufrufen kann, um eine andere Suche auszuführen, beginnend mit dem letzten Ende.

Explizit benannte Erfassungen

In herkömmlichen regulären Ausdrücken werden erfassende Klammern automatisch fortlaufend nummeriert. Dies führt zu zwei Problemen. Erstens muss, wenn ein regulärer Ausdruck durch das Einfügen oder Entfernen eines Klammerpaarsatzes geändert wird, der gesamte Code, der auf die nummerierten Erfassungsgruppen verweist, überarbeitet werden, um die neue Nummerierung zu berücksichtigen. Zweitens, da verschiedene Klammern häufig verwendet werden, um zwei alternative Ausdrücke für eine akzeptable Übereinstimmung bereitzustellen, kann es schwierig sein zu bestimmen, welche der beiden Ausdrücke tatsächlich ein Ergebnis zurückgegeben haben.

Um diese Probleme zu beheben, unterstützt die Regex Klasse die Syntax (?<name>…) zum Erfassen einer Übereinstimmung in einem angegebenen Steckplatz (der Slot kann mit einer Zeichenfolge oder einer ganzen Zahl benannt werden; ganze Zahlen können schneller zurückgerufen 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.)

Siehe auch