Esempio di espressione regolare: analisi di HREFs

L'esempio seguente cerca in una stringa di input e visualizza tutti i valori href="..." e le relative posizioni nella stringa.

Avvertimento

L'uso senza restrizioni di System.Text.RegularExpressions con input non attendibile può esporre le applicazioni ad attacchi di negazione del servizio. Per indicazioni su come usare in modo sicuro .NET espressioni regolari con input non attendibile, vedere Procedure consigliate per le espressioni regolari in .NET.

Oggetto Regex

Poiché il DumpHRefs metodo può essere chiamato più volte dal codice utente, usa il static metodo (Shared in Visual Basic). Regex.Match(String, String, RegexOptions) Ciò consente al motore delle espressioni regolari di memorizzare nella cache l'espressione regolare ed evita il sovraccarico derivante dalla creazione di un nuovo oggetto Regex ogni volta che viene chiamato il metodo. Si utilizza quindi un oggetto Match per iterare su tutte le corrispondenze nella stringa.

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

Nell'esempio seguente viene quindi illustrata una chiamata al DumpHRefs metodo .

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

Il criterio di espressione regolare href\s*=\s*(?:["'](?<1>[^"']*)["']|(?<1>[^>\s]+)) è interpretato nel modo illustrato nella tabella seguente.

Pattern Description
href Trovare la corrispondenza con la stringa letterale "href". La corrispondenza non fa distinzione tra maiuscole e minuscole.
\s* Corrispondere a zero o più caratteri di spazio bianco.
= Abbina il segno di uguale.
\s* Corrispondere a zero o più caratteri di spazio bianco.
(?: Avviare un gruppo non di acquisizione.
["'](?<1>[^"']*)["'] Trova la corrispondenza tra virgolette o apostrofo, seguita da un gruppo di acquisizione che corrisponde a qualsiasi carattere diverso da una virgoletta o un apostrofo, seguito da una virgoletta o un apostrofo. Il gruppo denominato 1 è incluso in questo modello.
| OR booleano che corrisponde all'espressione precedente o all'espressione successiva.
(?<1>[^>\s]+) Gruppo di acquisizione che usa un set negato per trovare una corrispondenza con qualsiasi carattere diverso da un segno maggiore o da uno spazio vuoto. Il gruppo denominato 1 è incluso in questo modello.
) Terminare il gruppo non di acquisizione.

Classe risultato corrispondenza

I risultati di una ricerca vengono archiviati nella Match classe , che consente di accedere a tutte le sottostringhe estratte dalla ricerca. Ricorda anche la stringa in cui viene eseguita la ricerca e l'espressione regolare usata, in modo da poter chiamare il Match.NextMatch metodo per eseguire un'altra ricerca a partire da dove è terminato l'ultimo.

Acquisizioni denominate in modo esplicito

Nelle espressioni regolari tradizionali, le parentesi di acquisizione vengono numerate automaticamente in sequenza. Ciò comporta due problemi. In primo luogo, se un'espressione regolare viene modificata inserendo o rimuovendo un set di parentesi, tutto il codice che fa riferimento alle acquisizioni numerate deve essere riscritto per riflettere la nuova numerazione. In secondo luogo, poiché vengono spesso usati set diversi di parentesi per fornire due espressioni alternative per una corrispondenza accettabile, potrebbe essere difficile determinare quale delle due espressioni ha effettivamente restituito un risultato.

Per risolvere questi problemi, la Regex classe supporta la sintassi (?<name>…) per l'acquisizione di una corrispondenza in uno slot specificato (lo slot può essere denominato usando una stringa o un numero intero; i numeri interi possono essere richiamati più rapidamente). Di conseguenza, tutte le corrispondenze alternative per la stessa stringa possono essere indirizzate allo stesso punto. In caso di conflitto, l'ultima corrispondenza inserita in uno slot è quella valida. (Tuttavia, è disponibile un elenco completo delle corrispondenze multiple per un singolo slot. Per ulteriori dettagli, vedere la raccolta Group.Captures.)

Vedere anche