規則運算式範例:掃描 HREF

下列範例將搜尋輸入字串,並顯示所有 href="..." 值和它們在字串中的位置。

警告

使用 System.Text.RegularExpressions 來處理不受信任的輸入時,請傳遞逾時。 惡意使用者可以提供輸入給 RegularExpressions,導致拒絕服務的攻擊。 使用 RegularExpressions 的 ASP.NET Core 架構 API 會傳遞逾時。

Regex 物件

由於可從使用者程式碼多次呼叫 DumpHRefs 方法,因此它會使用 static (在 Visual Basic 中為 Shared) Regex.Match(String, String, RegexOptions) 方法。 這可讓規則運算式引擎快取規則運算式,並避免在每次呼叫方法時因將新 Regex 物件具現化而導致的額外負荷。 接著會使用 Match 物件逐一查看字串中的所有相符項目。

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

下列範例說明如何呼叫 DumpHRefs 方法。

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

規則運算式模式 href\s*=\s*(?:["'](?<1>[^"']*)["']|(?<1>[^>\s]+)) 的解譯方式如下表所示。

模式 描述
href 比對常值字串 "href"。 該比對不區分大小寫。
\s* 比對零個以上的空白字元。
= 比對等號。
\s* 比對零個以上的空白字元。
(?: 啟動非擷取群組。
["'](?<1>[^"']*)["'] 比對引號 (或單引號),後面接著符合引號 (或單引號) 以外的任何字元的擷取群組,再加上引號 (或單引號)。 此模式中包含名為 1 的群組。
| 符合上一個運算式或下一個運算式的布林值 OR。
(?<1>[^>\s]+) 擷取群組,此群組會使用否定集來比對任何大於正負號或空白字元以外的字元。 此模式中包含名為 1 的群組。
) 結束非擷取群組。

比對結果類別

搜尋的結果會儲存在 Match 類別中,可讓您存取搜尋擷取的所有子字串。 它也會記住要搜尋的字串與所用的規則運算式,使其能呼叫 Match.NextMatch 方法,從最後一個搜尋結束的位置開始執行其他搜尋。

明確命名的擷取

在傳統的規則運算式中,會自動將擷取括號依序編號。 這會導致兩個問題。 第一,如果修改規則運算式時,是以插入或移除一組括號來進行,就必須重新撰寫所有參考已編號擷取的程式碼,以反映新的編號。 第二,不同的括號通常用來提供兩個替代運算式以進行可接受的比對,因此可能難以判斷這兩個運算式是哪一個實際傳回結果。

為了解決這些問題,Regex 類別支援 (?<name>…) 的語法,可將相符項目擷取至指定的位置 (該位置可以使用字串或整數命名;重新叫用整數的速度更快)。 因此,相同字串的所有替代比對皆可導向相同的位置。 萬一發生衝突時,最後一個進入位置的比對就是成功的比對 (不過,您可以使用單一位置之多個比對的完整清單。如需詳細資訊,請參閱 Group.Captures 集合。)

另請參閱