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é množství textu na:

  • Vyhledání konkrétních vzorů znaků
  • Ověřte text a ujistěte se, že odpovídá předdefinovanému vzoru (například e-mailové adrese).
  • Extrahování, úprava, nahrazení nebo odstranění podřetědců textu
  • Přidejte do kolekce extrahované řetězce, 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 s regulárními výrazy je modul regulárních výrazů, který je reprezentován objektem System.Text.RegularExpressions.Regex v .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 naleznete v tématu Jazyk regulárních výrazů – stručná referenční dokumentace.

  • 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 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ší 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.

Upozorňující

Při zpracování System.Text.RegularExpressions nedůvěryhodného vstupu předejte vypršení časového limitu. Uživatel se zlými úmysly může poskytnout vstup RegularExpressions, což způsobí útok na dostupnost služby. ASP.NET rozhraní API architektury Core, která používají RegularExpressions vypršení časového limitu.

Tip

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. Třída například TagRegex identifikuje počáteční značky v řetězci a CommentRegex třída identifikuje ASP.NET komentáře v řetězci.

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

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.). 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í 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í. 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("{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 \b(\w+?)\s\1\b regulárního výrazu lze interpretovat takto:

Vzor Interpretace
\b Začne na hranici slova.
(\w+?) Porovná jeden nebo více znaků slova, ale co 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ěžce, 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ězce "this? Tento“. 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 jazykovou verzi

Následující příklad znázorňuje sílu 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.

V počítači, jehož aktuální jazyková verze je angličtina - USA (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 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 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 řídicí znak.
\s* Vyhledá žádný nebo několik výskytů znaku mezery.
[-+]? 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 zachycenou skupinu nebo 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 celou 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 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á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 sadě Visual Studio

Reference