System.Text.RegularExpressions.Regex – třída

Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.

Třída Regex představuje . Modul regulárních výrazů technologie NET. Tuto třídu můžete použít k:

  • Rychle parsujte velké množství textu a vyhledejte konkrétní vzory znaků.
  • Extrahování, úprava, nahrazení nebo odstranění podřetědců textu
  • Přidejte extrahované řetězce do kolekce a vygenerujte sestavu.

Poznámka:

Pokud chcete ověřit řetězec tak, že určíte, jestli odpovídá určitému vzoru regulárního výrazu System.Configuration.RegexStringValidator , můžete použít třídu.

Chcete-li použít regulární výrazy, definujete vzor, který chcete identifikovat v textovém streamu pomocí syntaxe popsané v jazyce regulárních výrazů – stručná referenční dokumentace. Dále můžete volitelně vytvořit instanci objektu Regex . Nakonec zavoláte metodu, která provádí určitou operaci, například nahrazení textu, který odpovídá vzoru regulárního výrazu, nebo identifikaci shody vzoru.

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

Stručná referenční dokumentace ve formátu Wordu (.docx) ve formátuPDF (.pdf)

Regulární vs. řetězcové metody

Třída System.String obsahuje několik metod vyhledávání a porovnání, které můžete použít k provedení porovnávání vzorů s textem. Například , String.EndsWitha metody určují, String.Containszda řetězec instance obsahuje zadaný podřetězce; a String.IndexOf, String.IndexOfAnyString.LastIndexOf, a metody vrátí String.LastIndexOfAny počáteční pozici zadaného podřetězce v řetězciString.StartsWith. System.String Metody třídy použijte při hledání konkrétního řetězce. Regex Třídu použijte při hledání konkrétního vzoru v řetězci. Další informace a příklady naleznete v tématu Regulární výrazy .NET.

Statické a instance metody

Jakmile definujete vzor regulárního výrazu, můžete ho poskytnout modulu regulárních výrazů jedním ze dvou způsobů:

  • Vytvoření instance objektu Regex , který představuje regulární výraz. Uděláte to tak, že předáte vzor regulárního výrazu konstruktoru Regex . Objekt Regex je neměnný. Když vytvoříte instanci objektu Regex s regulárním výrazem, nelze regulární výraz objektu změnit.

  • Zadáním regulárního výrazu i textu pro vyhledávání do static metody (Sharedv jazyce Visual Basic) Regex To vám umožní použít regulární výraz bez explicitního vytvoření objektu Regex .

Všechny Regex metody identifikace vzorů zahrnují statické přetížení i přetížení instancí.

Modul regulárních výrazů musí před použití vzoru zkompilovat konkrétní vzor. Vzhledem k tomu Regex , že objekty jsou neměnné, jedná se o jednorázovou proceduru, která nastane při Regex volání konstruktoru třídy nebo statické metody. Aby se zabránilo nutnosti opakované kompilace jednoho regulárního výrazu, modul regulárních výrazů ukládá kompilované regulární výrazy použité ve voláních statických metod do mezipaměti. V důsledku toho metody porovnávání vzorů regulárních výrazů nabízejí srovnatelný výkon pro statické metody a metody instancí. Ukládání do mezipaměti však může nepříznivě ovlivnit výkon v následujících dvou případech:

  • Pokud používáte volání statické metody s velkým počtem regulárních výrazů. Modul regulárních výrazů ve výchozím nastavení ukládá do mezipaměti 15 naposledy použitých statických regulárních výrazů. Pokud vaše aplikace používá více než 15 statických regulárních výrazů, musí se některé regulární výrazy překompilovat. Chcete-li zabránit této rekompilace, můžete Regex.CacheSize zvýšit vlastnost.

  • Při vytváření instancí nových Regex objektů s regulárními výrazy, které byly dříve zkompilovány. Například následující kód definuje regulární výraz pro vyhledání duplicitních slov v textovém streamu. I když příklad používá jeden regulární výraz, vytvoří instanci nového Regex objektu pro zpracování každého řádku textu. Výsledkem je rekompilace regulárního výrazu s každou iterací smyčky.

    StreamReader sr = new StreamReader(filename);
    string input;
    string pattern = @"\b(\w+)\s\1\b";
    while (sr.Peek() >= 0)
    {
       input = sr.ReadLine();
       Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
       MatchCollection matches = rgx.Matches(input);
       if (matches.Count > 0)
       {
          Console.WriteLine("{0} ({1} matches):", input, matches.Count);
          foreach (Match match in matches)
             Console.WriteLine("   " + match.Value);
       }
    }
    sr.Close();
    
    Dim sr As New StreamReader(filename)
    Dim input As String
    Dim pattern As String = "\b(\w+)\s\1\b"
    Do While sr.Peek() >= 0
       input = sr.ReadLine()
       Dim rgx As New Regex(pattern, RegexOptions.IgnoreCase)
       Dim matches As MatchCollection = rgx.Matches(input)
       If matches.Count > 0 Then
          Console.WriteLine("{0} ({1} matches):", input, matches.Count)
          For Each match As Match In matches
             Console.WriteLine("   " + match.Value)
          Next   
       End If
    Loop
    sr.Close()
    

    Chcete-li zabránit rekompilace, měli byste vytvořit instanci jednoho Regex objektu, který je přístupný pro veškerý kód, který ho vyžaduje, jak je znázorněno v následujícím přepsaném příkladu.

    StreamReader sr = new StreamReader(filename);
    string input;
    string pattern = @"\b(\w+)\s\1\b";
    Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
    
    while (sr.Peek() >= 0)
    {
       input = sr.ReadLine();
       MatchCollection matches = rgx.Matches(input);
       if (matches.Count > 0)
       {
          Console.WriteLine("{0} ({1} matches):", input, matches.Count);
          foreach (Match match in matches)
             Console.WriteLine("   " + match.Value);
       }
    }
    sr.Close();
    
    Dim sr As New StreamReader(filename)
    Dim input As String
    Dim pattern As String = "\b(\w+)\s\1\b"
    Dim rgx As New Regex(pattern, RegexOptions.IgnoreCase)
    Do While sr.Peek() >= 0
       input = sr.ReadLine()
       Dim matches As MatchCollection = rgx.Matches(input)
       If matches.Count > 0 Then
          Console.WriteLine("{0} ({1} matches):", input, matches.Count)
          For Each match As Match In matches
             Console.WriteLine("   " + match.Value)
          Next   
       End If
    Loop
    sr.Close()
    

Provádění operací regulárního výrazu

Bez ohledu na to, jestli se rozhodnete vytvořit instanci objektu Regex a volat jeho metody nebo volat statické metody, Regex třída nabízí následující funkce porovnávání vzorů:

  • Ověření shody Zavoláte metodu IsMatch , která určí, jestli je k dispozici shoda.

  • Načtení jedné shody Zavoláte metodu Match pro načtení objektu Match , který představuje první shodu v řetězci nebo v části řetězce. Následné shody lze načíst voláním Match.NextMatch metody.

  • Načtení všech shod. Zavoláte metodu Matches pro načtení objektu System.Text.RegularExpressions.MatchCollection , který představuje všechny shody nalezené v řetězci nebo v části řetězce.

  • Nahrazení odpovídajícího textu Zavoláte metodu Replace , která nahradí odpovídající text. Náhradní text lze také definovat regulárním výrazem. Některé metody Replace navíc obsahují MatchEvaluator parametr, který umožňuje programově definovat náhradní text.

  • Vytvoření pole řetězců, které je tvořeno částmi vstupního řetězce. Zavoláte metodu Split rozdělení vstupního řetězce na pozicích, které jsou definovány regulárním výrazem.

Kromě metod porovnávání vzorů Regex zahrnuje třída několik speciálních metod:

  • Metoda Escape uchycuje všechny znaky, které mohou být interpretovány jako operátory regulárního výrazu v regulárním výrazu nebo vstupním řetězci.
  • Metoda Unescape odebere tyto řídicí znaky.
  • Metoda CompileToAssembly vytvoří sestavení, které obsahuje předdefinované regulární výrazy. .NET obsahuje příklady těchto speciálních sestavení v System.Web.RegularExpressions oboru názvů.

Definování hodnoty časového limitu

.NET podporuje plně funkční jazyk regulárních výrazů, který poskytuje značné možnosti a flexibilitu při porovnávání vzorů. Výkon a flexibilita ale stojí: riziko nízkého výkonu. Regulární výrazy, které fungují špatně, jsou překvapivě snadno vytvořené. V některých případech se operace regulárních výrazů, které spoléhají na nadměrné navracení, mohou při zpracování textu, který téměř odpovídá vzoru regulárního výrazu, přestat reagovat. Další informace o modulu regulárních výrazů .NET naleznete v tématu Podrobnosti o chování regulárního výrazu. Další informace o nadměrném navracení najdete v tématu Navracení.

Počínaje rozhraním .NET Framework 4.5 můžete definovat interval časového limitu pro shodu regulárního výrazu, abyste omezili nadměrné navracení. V závislosti na vzoru regulárního výrazu a vstupním textu může doba provádění překročit zadaný interval časového limitu, ale nebude trávit více času navracením, než je zadaný interval časového limitu. Pokud vyprší časový limit modulu regulárních výrazů RegexMatchTimeoutException , vyvolá výjimku. Ve většině případů to zabrání stroji regulárních výrazů v plýtvání výpočetním výkonem tím, že se pokusí spárovat text, který téměř odpovídá vzoru regulárního výrazu. Může to ale také znamenat, že časový limit byl nastaven příliš nízký nebo že aktuální zatížení počítače způsobilo celkové snížení výkonu.

Způsob zpracování výjimky závisí na příčině výjimky. Pokud k výjimce dojde, protože je nastavený příliš nízký časový limit nebo kvůli nadměrnému zatížení počítače, můžete zvýšit interval časového limitu a zkusit opakovat odpovídající operaci. Pokud dojde k výjimce, protože regulární výraz spoléhá na nadměrné navracení, můžete předpokládat, že shoda neexistuje, a volitelně můžete protokolovat informace, které vám pomůžou upravit vzor regulárního výrazu.

Časový limit můžete nastavit voláním konstruktoru Regex(String, RegexOptions, TimeSpan) při vytvoření instance objektu regulárního výrazu. U statických metod můžete nastavit časový limit voláním přetížení odpovídající metody, která má matchTimeout parametr. Pokud hodnotu časového limitu nenastavíte explicitně, výchozí hodnota časového limitu se určí takto:

  • Pokud existuje, použijte hodnotu časového limitu pro celou aplikaci. Nastavte hodnotu časového limitu pro celou aplikaci voláním AppDomain.SetData metody pro přiřazení řetězcové TimeSpan reprezentace hodnoty vlastnosti REGEX_DEFAULT_MATCH_TIMEOUT .
  • Pokud nebyla nastavena žádná hodnota časového limitu pro celou aplikaci, použije se tato hodnota InfiniteMatchTimeout.

Důležité

Doporučujeme nastavit hodnotu časového limitu ve všech operacích porovnávání vzorů regulárních výrazů. Další informace najdete v tématu Osvědčené postupy pro regulární výrazy.

Příklady

Následující příklad používá regulární výraz ke kontrole opakovaných výskytů slov v řetězci. Regulární výraz \b(?<word>\w+)\s+(\k<word>)\b lze interpretovat, jak je znázorněno v následující tabulce.

Vzor Popis
\b Zahajte shodu na hranici slova.
(?<word>\w+) Porovná jeden nebo více znaků slova až do hranice slova. Pojmenujte tuto zachycenou skupinu word.
\s+ Porovná jeden nebo více prázdných znaků.
(\k<word>) Porovná zachycenou skupinu s názvem word.
\b Porovná hranici slova.
using System;
using System.Text.RegularExpressions;

public class Test
{
    public static void Main ()
    {
        // Define a regular expression for repeated words.
        Regex rx = new Regex(@"\b(?<word>\w+)\s+(\k<word>)\b",
          RegexOptions.Compiled | RegexOptions.IgnoreCase);

        // Define a test string.
        string text = "The the quick brown fox  fox jumps over the lazy dog dog.";

        // Find matches.
        MatchCollection matches = rx.Matches(text);

        // Report the number of matches found.
        Console.WriteLine("{0} matches found in:\n   {1}",
                          matches.Count,
                          text);

        // Report on each match.
        foreach (Match match in matches)
        {
            GroupCollection groups = match.Groups;
            Console.WriteLine("'{0}' repeated at positions {1} and {2}",
                              groups["word"].Value,
                              groups[0].Index,
                              groups[1].Index);
        }
    }
}

// The example produces the following output to the console:
//       3 matches found in:
//          The the quick brown fox  fox jumps over the lazy dog dog.
//       'The' repeated at positions 0 and 4
//       'fox' repeated at positions 20 and 25
//       'dog' repeated at positions 49 and 53
Imports System.Text.RegularExpressions

Public Module Test

    Public Sub Main()
        ' Define a regular expression for repeated words.
        Dim rx As New Regex("\b(?<word>\w+)\s+(\k<word>)\b", _
               RegexOptions.Compiled Or RegexOptions.IgnoreCase)

        ' Define a test string.        
        Dim text As String = "The the quick brown fox  fox jumps over the lazy dog dog."
        
        ' Find matches.
        Dim matches As MatchCollection = rx.Matches(text)

        ' Report the number of matches found.
        Console.WriteLine("{0} matches found in:", matches.Count)
        Console.WriteLine("   {0}", text)

        ' Report on each match.
        For Each match As Match In matches
            Dim groups As GroupCollection = match.Groups
            Console.WriteLine("'{0}' repeated at positions {1} and {2}", _ 
                              groups.Item("word").Value, _
                              groups.Item(0).Index, _
                              groups.Item(1).Index)
        Next
    End Sub
End Module
' The example produces the following output to the console:
'       3 matches found in:
'          The the quick brown fox  fox jumps over the lazy dog dog.
'       'The' repeated at positions 0 and 4
'       'fox' repeated at positions 20 and 25
'       'dog' repeated at positions 49 and 53

Následující příklad ukazuje použití regulárního výrazu ke kontrole, zda řetězec představuje hodnotu měny nebo má správný formát představující hodnotu měny. V tomto případě se regulární výraz sestavuje dynamicky z NumberFormatInfo.CurrencyDecimalSeparatorjazykové verze en-US , CurrencyDecimalDigits, NumberFormatInfo.CurrencySymbolNumberFormatInfo.NegativeSigna NumberFormatInfo.PositiveSign vlastnosti. Výsledný regulární výraz je ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$. Tento regulární výraz lze interpretovat, jak je znázorněno v následující tabulce.

Vzor Popis
^ Začněte na začátku řetězce.
\s* Porovná žádný nebo více prázdných znaků.
[\+-]? Porovná žádný nebo jeden výskyt kladného nebo záporného znaménka.
\s? Porovná žádný nebo jeden prázdný znak.
\$? Porovná žádný nebo jeden výskyt znaku dolaru.
\s? Porovná žádný nebo jeden prázdný znak.
\d* Porovná žádnou nebo několik desítkových číslic.
\.? Porovná symbol nuly nebo jedné desetinné čárky.
(\d{2})? Zachytávání skupiny 1: Porovná dvě desetinné číslice nula nebo jednou.
(\d*\.?(\d{2})?){1} Porovná vzor integrálních a desetinných číslic oddělených desetinnou čárkou alespoň jednou.
$ Porovná konec řetězce.

V tomto případě regulární výraz předpokládá, že platný řetězec měny neobsahuje symboly oddělovače skupin a že neobsahuje desetinné číslice ani počet desetinných číslic definovaných zadanou vlastností jazykové verze CurrencyDecimalDigits .

using System;
using System.Globalization;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        // Get the en-US NumberFormatInfo object to build the regular 
        // expression pattern dynamically.
        NumberFormatInfo nfi = CultureInfo.GetCultureInfo("en-US").NumberFormat;

        // Define the regular expression pattern.
        string pattern;
        pattern = @"^\s*[";
        // Get the positive and negative sign symbols.
        pattern += Regex.Escape(nfi.PositiveSign + nfi.NegativeSign) + @"]?\s?";
        // Get the currency symbol.
        pattern += Regex.Escape(nfi.CurrencySymbol) + @"?\s?";
        // Add integral digits to the pattern.
        pattern += @"(\d*";
        // Add the decimal separator.
        pattern += Regex.Escape(nfi.CurrencyDecimalSeparator) + "?";
        // Add the fractional digits.
        pattern += @"(\d{";
        // Determine the number of fractional digits in currency values.
        pattern += nfi.CurrencyDecimalDigits.ToString() + "})?){1}$";

        Console.WriteLine($"Pattern is {pattern}\n");

        Regex rgx = new Regex(pattern);

        // Define some test strings.
        string[] tests = { "-42", "19.99", "0.001", "100 USD",
                         ".34", "0.34", "1,052.21", "$10.62",
                         "+1.43", "-$0.23" };

        // Check each test string against the regular expression.
        foreach (string test in tests)
        {
            if (rgx.IsMatch(test))
                Console.WriteLine($"{test} is a currency value.");
            else
                Console.WriteLine($"{test} is not a currency value.");
        }
    }
}
// The example displays the following output:
//       Pattern is ^\s*[\+-]?\s?\$?\s?(\d*\.?(\d{2})?){1}$
//
//       -42 is a currency value.
//       19.99 is a currency value.
//       0.001 is not a currency value.
//       100 USD is not a currency value.
//       .34 is a currency value.
//       0.34 is a currency value.
//       1,052.21 is not a currency value.
//       $10.62 is a currency value.
//       +1.43 is a currency value.
//       -$0.23 is a currency value.
Imports System.Globalization
Imports System.Text.RegularExpressions

Public Module Example
   Public Sub Main()
      ' Get the current NumberFormatInfo object to build the regular 
      ' expression pattern dynamically.
      Dim nfi As NumberFormatInfo = CultureInfo.GetCultureInfo("en-US").NumberFormat

      ' Define the regular expression pattern.
      Dim pattern As String 
      pattern = "^\s*["
      ' Get the positive and negative sign symbols.
      pattern += Regex.Escape(nfi.PositiveSign + nfi.NegativeSign) + "]?\s?"
      ' Get the currency symbol.
      pattern += Regex.Escape(nfi.CurrencySymbol) + "?\s?"
      ' Add integral digits to the pattern.
      pattern += "(\d*"
      ' Add the decimal separator.
      pattern += Regex.Escape(nfi.CurrencyDecimalSeparator) + "?"
      ' Add the fractional digits.
      pattern += "(\d{"
      ' Determine the number of fractional digits in currency values.
      pattern += nfi.CurrencyDecimalDigits.ToString() + "})?){1}$"
      
      Console.WriteLine("Pattern is {0}", pattern)
      Console.WriteLine()
      
      Dim rgx As New Regex(pattern)

      ' Define some test strings.
      Dim tests() As String = {"-42", "19.99", "0.001", "100 USD", _
                               ".34", "0.34", "1,052.21", "$10.62", _
                               "+1.43", "-$0.23" }

      ' Check each test string against the regular expression.
      For Each test As String In tests
         If rgx.IsMatch(test) Then
            Console.WriteLine("{0} is a currency value.", test)
         Else
            Console.WriteLine("{0} is not a currency value.", test)
         End If
      Next
   End Sub
End Module
' The example displays the following output:
'       Pattern is ^\s*[\+-]?\s?\$?\s?(\d*\.?(\d{2})?){1}$
'
'       -42 is a currency value.
'       19.99 is a currency value.
'       0.001 is not a currency value.
'       100 USD is not a currency value.
'       .34 is a currency value.
'       0.34 is a currency value.
'       1,052.21 is not a currency value.
'       $10.62 is a currency value.
'       +1.43 is a currency value.
'       -$0.23 is a currency value.

Vzhledem k tomu, že regulární výraz v tomto příkladu je vytvořený dynamicky, nevíte v době návrhu, jestli je symbol měny, desetinné číslo nebo kladné a záporné znaménko zadané jazykové verze (v tomto příkladu en-US) chybně interpretován modulem regulárních výrazů jako operátory jazyka regulárního výrazu. Aby se zabránilo nesprávné interpretaci, předá příklad každému dynamicky generovanému Escape řetězci metodě.