Regulární výrazy .NET

Regulární výrazy poskytují výkonný, flexibilní a efektivní způsob zpracování textu. Rozsáhlá notace porovnávání vzorů regulárních výrazů umožňuje rychle analyzovat velké objemy textu na:

  • Vyhledání konkrétních vzorů znaků
  • Ověřte text, abyste zajistili, že odpovídá předdefinovanému vzoru (například e-mailové adrese).
  • Extrahujte, upravte, nahraďte nebo odstraňte podřetězce textu.
  • Přidejte extrahované řetězce do kolekce, aby se vygenerovala sestava.

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

Jak fungují regulární výrazy

Středem zpracování textu pomocí regulárních výrazů je modul regulárních výrazů, který je System.Text.RegularExpressions.Regex reprezentován objektem v rozhraní .NET. Požadované minimum pro zpracování textu pomocí regulárních výrazů je předání následujících dvou informací modulu regulárních výrazů:

  • 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 najdete v tématu Jazyk regulárních výrazů – stručná referenční příručka.

  • Text určený k analýze pomocí vzoru regulárního výrazu.

Metody třídy Regex umožňují provedení následujících operací:

Přehled objektového modelu regulárního výrazu najdete v tématu Objektový model regulárního výrazu.

Další informace o jazyce regulárních výrazů najdete v tématu Jazyk regulárních výrazů – stručné referenční informace nebo si stáhněte a vytiskněte jednu z těchto možností:

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

Třída String zahrnuje celou řadu metod pro vyhledání nebo nahrazení řetězce, které lze ve větším řetězci použít při vyhledávání textových literálů. Regulární výrazy jsou nejužitečnější při hledání jednoho nebo více dílčích podřetězců ve větším řetězci, nebo při identifikaci vzorů v řetězci, jak je znázorněno v následujícím příkladu.

Upozornění

Při použití System.Text.RegularExpressions ke zpracování nedůvěryhodného vstupu předejte časový limit. Uživatel se zlými úmysly může poskytnout vstup pro RegularExpressions útok DoS (Denial-of-Service). Rozhraní API rozhraní ASP.NET Core Framework, která používají RegularExpressions předávat časový limit.

Tip

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

Příklad 1: Nahrazení podřetězců

Předpokládejme seznam, který obsahuje jména a který může u jména a příjmení zahrnovat také oslovení (Mr., Mrs., Miss, nebo Ms.). Pokud při vytváření popisků ze seznamu nechcete oslovení zahrnout, můžete oslovení odstranit pomocí regulárního výrazu, jak je znázorněno v následujícím příkladu.

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 odpovídá libovolnému výskytu (Mr\.? |Mrs\.? |Miss |Ms\.? ) "Mr", "Mr. ", "Mrs ", "Mrs. ", "Miss ", "Ms nebo "Ms. ". Volání metody Regex.Replace nahradí vyhledaný řetězec String.Empty; jinými slovy to znamená, že jej z původního řetězce odstraní.

Příklad 2: Identifikace duplicitních slov

Nechtěně zdvojená slova jsou běžnou chybou, které se autoři při psaní dopouštějí. Zdvojená slova mohou být vyhledána pomocí regulárního výrazu, jak znázorňuje 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("{0} (duplicates '{1}') at position {2}",
                           match.Value, match.Groups[1].Value, 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 \b(\w+?)\s\1\b výrazu lze interpretovat takto:

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

Metoda Regex.Matches je zavolána pomocí možností regulárního výrazu, které jsou nastaveny jako RegexOptions.IgnoreCase. Operace shody proto rozlišuje velká a malá písmena a příklad vyhodnotí podřetězec „Tento tento“ jako zdvojené slovo.

Vstupní řetězec obsahuje podřetězec "this? Tento“. Z důvodu výskytu otazníku však nedojde k vyhodnocení výrazu jako zdvojeného slova.

Příklad 3: Dynamické sestavení regulárního výrazu citlivého na jazykovou verzi

Následující příklad znázorňuje výkon regulárních výrazů v kombinaci s flexibilitou, kterou nabízí . Funkce globalizace technologie NET. Formát měny v aktuální jazykové verzi systému určuje objekt NumberFormatInfo. Tuto informaci následně používá k vytvoření regulárního výrazu, který z textu extrahuje hodnoty měny. Pro jednotlivé shody extrahuje podskupinu obsahující pouze číselný řetězec, převede jej na hodnotu Decimal a vypočte mezisouč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 {0} matches.", matches.Count);

      // 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 {0:C2}.", expenses[expenses.Count - 1]);
      else
         Console.WriteLine("The expenses total {0:C2}.", total);
   }
}
// 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.

Na počítači, jehož aktuální jazyková verze je angličtina – USA (en-US), příklad dynamicky sestaví regulární výraz \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?) . Tento vzor regulárního výrazu může být interpretován takto:

Vzor Interpretace
\$ Ve vstupním řetězci vyhledejte jeden výskyt symbolu dolaru ( $ ). Vzor regulárního výrazu obsahuje zpětné lomítko pro označení toho, zda bude symbol dolaru spíše interpretován doslovně, než aby byl použit jako ukotvení regulárního výrazu. (Samotný symbol by indikuje, že by se modul regulárních výrazů měl pokusit zahájit svou shodu na $ konci řetězce.) Aby se zajistilo, že symbol měny aktuální jazykové verze není přeinterpretován jako symbol regulárního výrazu, volá příklad metodu , která znak Regex.Escape řídicí.
\s* Vyhledá žádný nebo několik výskytů znaku mezery.
[-+]? Vyhledá žádný nebo jeden ze znaků plus nebo mínus.
([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?) Vnější závorky výrazu jej definují jako zachytávající skupinu nebo jako dílčí výraz. Při nalezení shody může být informace o části vyhovujícího řetězce vrácena druhým objektem Group v rámci objektu GroupCollection vráceného vlastností Match.Groups. (První prvek v kolekci představuje celkovou shodu.)
[0-9]{0,3} Vyhledá žádný až tři výskyty desítkových číslic od 0 do 9.
(,[0-9]{3})* Vyhledá žádný nebo několik výskytů oddělovače skupin, za kterým následují tři desítkové číslice.
\. Vyhledá jeden výskyt oddělovače desetinných míst.
[0-9]+ Vyhledá jednu nebo několik desítkových číslic.
(\.[0-9]+)? Vyhledá žádný nebo jeden výskyt oddělovače desetinných míst následovaného alespoň jednou desítkovou číslicí.

Pokud je v rámci vstupního řetězce každý z těchto dílčích vzorů vyhledán, dojde k nalezení shody a objekt Match, který obsahuje informaci o shodě, je přidán do objektu MatchCollection.

Nadpis Popis
Jazyk regulárních výrazů – stručná referenční dokumentace Poskytuje informace o sadách znaků, operátorech a konstrukcích, které lze použít pro definování regulárních výrazů.
Model objektu regulárního výrazu Poskytuje informace a příklady kódu znázorňující způsob používání tříd regulárních výrazů.
Podrobnosti k 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ů v Visual Studio

Reference