Sdílet prostřednictvím


Regulární výrazy .NET

Regulární výrazy poskytují výkonnou, flexibilní a efektivní metodu pro zpracování textu. Rozsáhlá notace regulárních výrazů pro porovnávání vzorů umožňuje rychle zpracovat velké množství textu na:

  • Vyhledejte konkrétní vzory znaků.
  • Ověřte text, abyste měli jistotu, že odpovídá předdefinovanému vzoru (například e-mailové adrese).
  • Extrahujte, upravujte, nahrazujte nebo odstraňujte textové podřetětce.
  • Přidejte do kolekce extrahované řetězce za účelem generování sestavy.

Pro mnoho aplikací, které pracují s řetězci nebo parsují velké bloky textu, jsou regulární výrazy nepostradatelným nástrojem.

Jak fungují regulární výrazy

Středem zpracování textu s regulárními výrazy je modul regulárních výrazů, který je reprezentován objektem System.Text.RegularExpressions.Regex v .NET. Minimálně zpracování textu pomocí regulárních výrazů vyžaduje, aby modul regulárních výrazů poskytoval následující dvě informace:

  • Vzor regulárního výrazu pro identifikaci v textu.

    V .NET jsou vzory regulárních výrazů definovány speciální syntaxí nebo jazykem, který je kompatibilní s regulárními výrazy Perl 5 a přidává některé další funkce, jako je porovnávání zprava doleva. Další informace naleznete v tématu Jazyk regulárních výrazů – stručná referenční dokumentace.

  • Text, který se má analyzovat pro vzor regulárního výrazu.

Metody Regex třídy umožňují provádět následující operace:

Přehled objektového modelu regulárního výrazu naleznete v tématu Model objektu regulárního výrazu.

Další informace o jazyce regulárních výrazů naleznete v tématu Jazyk regulárních výrazů – stručná referenční dokumentace nebo stažení a tisk jedné z následujících brožur:

Příklady regulárních výrazů

Třída String obsahuje metody hledání a nahrazení řetězců, které můžete použít, když chcete vyhledat literály ve větším řetězci. Regulární výrazy jsou nejužitečnější buď v případě, že chcete vyhledat jeden z několika podřetězců ve větším řetězci, nebo když chcete identifikovat vzory v řetězci, jak je znázorněno v následujících příkladech.

Výstraha

Při zpracování nedůvěryhodného vstupu pomocí System.Text.RegularExpressions nastavte časový limit. Zlomyslný uživatel může zadat vstup do RegularExpressions, což způsobí útok typu odepření služby . ASP.NET Core rozhraní API, která používají RegularExpressions pro nastavení časového limitu.

Návod

Obor System.Web.RegularExpressions názvů obsahuje řadu objektů regulárních výrazů, které implementují předdefinované vzory regulárních výrazů pro analýzu řetězců z dokumentů HTML, XML a ASP.NET. Například třída TagRegex identifikuje počáteční značky v řetězci a třída CommentRegex identifikuje komentáře ASP.NET v řetězci.

Příklad 1: Náhrada podřetězců

Předpokládejme, že seznam adresátů obsahuje jména, která někdy obsahují název (pan, paní, slečna nebo slečna) spolu s křestním jménem a příjmením. Předpokládejme, že nechcete zahrnout názvy při generování štítků obálky ze seznamu. V takovém případě můžete k odebrání názvů použít regulární výraz, jak ukazuje následující příklad:

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "(Mr\\.? |Mrs\\.? |Miss |Ms\\.? )";
      string[] names = { "Mr. Henry Hunt", "Ms. Sara Samuels",
                         "Abraham Adams", "Ms. Nicole Norris" };
      foreach (string name in names)
         Console.WriteLine(Regex.Replace(name, pattern, String.Empty));
   }
}
// The example displays the following output:
//    Henry Hunt
//    Sara Samuels
//    Abraham Adams
//    Nicole Norris
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(Mr\.? |Mrs\.? |Miss |Ms\.? )"
        Dim names() As String = {"Mr. Henry Hunt", "Ms. Sara Samuels", _
                                  "Abraham Adams", "Ms. Nicole Norris"}
        For Each name As String In names
            Console.WriteLine(Regex.Replace(name, pattern, String.Empty))
        Next
    End Sub
End Module
' The example displays the following output:
'    Henry Hunt
'    Sara Samuels
'    Abraham Adams
'    Nicole Norris

Vzor regulárního výrazu (Mr\.? |Mrs\.? |Miss |Ms\.? ) odpovídá jakémukoli výskytu výrazu "Mr ", "Mr. ", "Paní ", "Paní. ", "Slečna ", "Slečna ", nebo "Paní. ". Volání na Regex.Replace metodu nahradí odpovídající řetězec řetězcem String.Empty; jinými slovy jej odstraní z původního řetězce.

Příklad 2: Identifikace duplicitních slov

Náhodné duplikování slov je běžnou chybou, kterou zapisovači dělají. Regulární výraz použijte k identifikaci duplicitních slov, jak ukazuje následující příklad:

using System;
using System.Text.RegularExpressions;

public class Class1
{
   public static void Main()
   {
      string pattern = @"\b(\w+?)\s\1\b";
      string input = "This this is a nice day. What about this? This tastes good. I saw a a dog.";
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
         Console.WriteLine($"{match.Value} (duplicates '{match.Groups[1].Value}') at position {match.Index}");
   }
}
// The example displays the following output:
//       This this (duplicates 'This') at position 0
//       a a (duplicates 'a') at position 66
Imports System.Text.RegularExpressions

Module modMain
    Public Sub Main()
        Dim pattern As String = "\b(\w+?)\s\1\b"
        Dim input As String = "This this is a nice day. What about this? This tastes good. I saw a a dog."
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
            Console.WriteLine("{0} (duplicates '{1}') at position {2}", _
                              match.Value, match.Groups(1).Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       This this (duplicates 'This') at position 0
'       a a (duplicates 'a') at position 66

Vzor regulárního výrazu \b(\w+?)\s\1\b lze interpretovat takto:

Vzor Výklad
\b Začněte na hranici slova.
(\w+?) Porovná jeden nebo více znaků slova, ale co nejméně znaků. Společně tvoří skupinu, která může být označována jako \1.
\s Porovná prázdný znak.
\1 Najde podřetězec, který se rovná skupině s názvem \1.
\b Najdi hranici slova.

Metoda Regex.Matches je volána s možnostmi regulárního výrazu nastavenými na RegexOptions.IgnoreCase. Proto je operace shody nerozlišující malá a velká písmena a příklad identifikuje podřetězec "This this" jako duplikaci.

Vstupní řetězec obsahuje podřetězce "this? Tohle". Z důvodu intervenující interpunkční znaméně se ale jako duplicita neidentifikuje.

Příklad 3: Dynamické sestavení regulárního výrazu citlivého na kulturní prostředí

Následující příklad znázorňuje sílu regulárních výrazů v kombinaci s flexibilitou, kterou nabízí funkce globalizace .NET. Objekt NumberFormatInfo používá k určení formátu hodnot měny v aktuální jazykové verzi systému. Pomocí této informace pak dynamicky vytvoří regulární výraz, který extrahuje hodnoty měny z textu. Pro každou shodu vyextrahuje podskupinu obsahující pouze číselný řetězec, převede ji na hodnotu Decimal a vypočítá průběžný součet.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      // Define text to be parsed.
      string input = "Office expenses on 2/13/2008:\n" +
                     "Paper (500 sheets)                      $3.95\n" +
                     "Pencils (box of 10)                     $1.00\n" +
                     "Pens (box of 10)                        $4.49\n" +
                     "Erasers                                 $2.19\n" +
                     "Ink jet printer                        $69.95\n\n" +
                     "Total Expenses                        $ 81.58\n";

      // Get current culture's NumberFormatInfo object.
      NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
      // Assign needed property values to variables.
      string currencySymbol = nfi.CurrencySymbol;
      bool symbolPrecedesIfPositive = nfi.CurrencyPositivePattern % 2 == 0;
      string groupSeparator = nfi.CurrencyGroupSeparator;
      string decimalSeparator = nfi.CurrencyDecimalSeparator;

      // Form regular expression pattern.
      string pattern = Regex.Escape( symbolPrecedesIfPositive ? currencySymbol : "") +
                       @"\s*[-+]?" + "([0-9]{0,3}(" + groupSeparator + "[0-9]{3})*(" +
                       Regex.Escape(decimalSeparator) + "[0-9]+)?)" +
                       (! symbolPrecedesIfPositive ? currencySymbol : "");
      Console.WriteLine( "The regular expression pattern is:");
      Console.WriteLine("   " + pattern);

      // Get text that matches regular expression pattern.
      MatchCollection matches = Regex.Matches(input, pattern,
                                              RegexOptions.IgnorePatternWhitespace);
      Console.WriteLine($"Found {matches.Count} matches.");

      // Get numeric string, convert it to a value, and add it to List object.
      List<decimal> expenses = new List<Decimal>();

      foreach (Match match in matches)
         expenses.Add(Decimal.Parse(match.Groups[1].Value));

      // Determine whether total is present and if present, whether it is correct.
      decimal total = 0;
      foreach (decimal value in expenses)
         total += value;

      if (total / 2 == expenses[expenses.Count - 1])
         Console.WriteLine($"The expenses total {expenses[expenses.Count - 1]:C2}.");
      else
         Console.WriteLine($"The expenses total {total:C2}.");
   }
}
// The example displays the following output:
//       The regular expression pattern is:
//          \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?)
//       Found 6 matches.
//       The expenses total $81.58.
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Text.RegularExpressions

Public Module Example
    Public Sub Main()
        ' Define text to be parsed.
        Dim input As String = "Office expenses on 2/13/2008:" + vbCrLf + _
                              "Paper (500 sheets)                      $3.95" + vbCrLf + _
                              "Pencils (box of 10)                     $1.00" + vbCrLf + _
                              "Pens (box of 10)                        $4.49" + vbCrLf + _
                              "Erasers                                 $2.19" + vbCrLf + _
                              "Ink jet printer                        $69.95" + vbCrLf + vbCrLf + _
                              "Total Expenses                        $ 81.58" + vbCrLf
        ' Get current culture's NumberFormatInfo object.
        Dim nfi As NumberFormatInfo = CultureInfo.CurrentCulture.NumberFormat
        ' Assign needed property values to variables.
        Dim currencySymbol As String = nfi.CurrencySymbol
        Dim symbolPrecedesIfPositive As Boolean = CBool(nfi.CurrencyPositivePattern Mod 2 = 0)
        Dim groupSeparator As String = nfi.CurrencyGroupSeparator
        Dim decimalSeparator As String = nfi.CurrencyDecimalSeparator

        ' Form regular expression pattern.
        Dim pattern As String = Regex.Escape(CStr(IIf(symbolPrecedesIfPositive, currencySymbol, ""))) + _
                                "\s*[-+]?" + "([0-9]{0,3}(" + groupSeparator + "[0-9]{3})*(" + _
                                Regex.Escape(decimalSeparator) + "[0-9]+)?)" + _
                                CStr(IIf(Not symbolPrecedesIfPositive, currencySymbol, ""))
        Console.WriteLine("The regular expression pattern is: ")
        Console.WriteLine("   " + pattern)

        ' Get text that matches regular expression pattern.
        Dim matches As MatchCollection = Regex.Matches(input, pattern, RegexOptions.IgnorePatternWhitespace)
        Console.WriteLine("Found {0} matches. ", matches.Count)

        ' Get numeric string, convert it to a value, and add it to List object.
        Dim expenses As New List(Of Decimal)

        For Each match As Match In matches
            expenses.Add(Decimal.Parse(match.Groups.Item(1).Value))
        Next

        ' Determine whether total is present and if present, whether it is correct.
        Dim total As Decimal
        For Each value As Decimal In expenses
            total += value
        Next

        If total / 2 = expenses(expenses.Count - 1) Then
            Console.WriteLine("The expenses total {0:C2}.", expenses(expenses.Count - 1))
        Else
            Console.WriteLine("The expenses total {0:C2}.", total)
        End If
    End Sub
End Module
' The example displays the following output:
'       The regular expression pattern is:
'          \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?)
'       Found 6 matches.
'       The expenses total $81.58.

V počítači, jehož aktuální jazyková verze je angličtina - Spojené státy (en-US), příklad dynamicky vytváří regulární výraz \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?). Tento vzor regulárního výrazu lze interpretovat takto:

Vzor Výklad
\$ Ve vstupním řetězci vyhledejte jeden výskyt symbolu dolaru ($). Řetězec vzoru regulárního výrazu obsahuje zpětné lomítko, které označuje, že symbol dolaru by měl být interpretován doslova, nikoliv jako kotva regulárního výrazu. Samotný $ symbol by značil, že modul regulárních výrazů by se měl pokusit zahájit shodu na konci řetězce. Aby se zajistilo, že symbol měny aktuální jazykové verze není chybně interpretován jako symbol regulárního výrazu, příklad volá metodu Regex.Escape pro úpravu tohoto znaku.
\s* Hledejte nula nebo více výskytů bílého znaku.
[-+]? Vyhledejte nulový nebo jeden výskyt kladného nebo záporného znaménka.
([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?) Vnější závorky definují tento výraz jako zachycovací skupinu nebo dílčí výraz. Pokud je nalezena shoda, informace o této části odpovídajícího řetězce lze načíst z druhého Group objektu v objektu GroupCollection vráceného Match.Groups vlastností. První prvek v kolekci představuje celou shodu.
[0-9]{0,3} Hledejte nula až tři výskyty číslic od 0 do 9.
(,[0-9]{3})* Vyhledejte nula nebo více výskytů oddělovače skupiny následovaných třemi desetinnými číslicemi.
\. Vyhledejte jeden výskyt oddělovače desetinných míst.
[0-9]+ Hledejte jednu nebo více desetinných číslic.
(\.[0-9]+)? Vyhledejte nula nebo jeden výskyt desetinné čárky, za kterým následuje alespoň jedna desetinná číslice.

Pokud se každý podpattern nachází ve vstupním řetězci, shoda proběhne úspěšně a Match objekt, který obsahuje informace o shodě, se přidá do objektu MatchCollection .

Titulek Popis
Jazyk regulárních výrazů – stručná referenční dokumentace Poskytuje informace o sadě znaků, operátorů a konstruktorů, které můžete použít k definování regulárních výrazů.
Model objektu regulárního výrazu Poskytuje informace a příklady kódu, které ilustrují použití tříd regulárních výrazů.
Podrobnosti o chování regulárních výrazů Poskytuje informace o možnostech a chování regulárních výrazů .NET.
Použití regulárních výrazů ve Visual Studiu

Odkazy