Udostępnij za pośrednictwem


System.Text.RegularExpressions.Regex, klasa

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Klasa Regex reprezentuje wartość . Aparat wyrażeń regularnych platformy NET. Tej klasy można użyć do:

  • Szybkie analizowanie dużych ilości tekstu w celu znalezienia określonych wzorców znaków.
  • Wyodrębnianie, edytowanie, zastępowanie lub usuwanie podciągów tekstowych.
  • Dodaj wyodrębnione ciągi do kolekcji, aby wygenerować raport.

Uwaga

Jeśli chcesz zweryfikować ciąg, określając, czy jest on zgodny z określonym wzorcem wyrażenia regularnego, możesz użyć System.Configuration.RegexStringValidator klasy .

Aby używać wyrażeń regularnych, należy zdefiniować wzorzec, który ma być identyfikowany w strumieniu tekstowym przy użyciu składni opisanej w języku wyrażeń regularnych — krótki przewodnik. Następnie możesz opcjonalnie utworzyć wystąpienie Regex obiektu. Na koniec wywołujesz metodę, która wykonuje jakąś operację, na przykład zamieniając tekst zgodny ze wzorcem wyrażenia regularnego lub identyfikując dopasowanie wzorca.

Aby uzyskać więcej informacji na temat języka wyrażeń regularnych, zobacz Język wyrażeń regularnych — szybkie informacje lub pobierz i wydrukuj jedną z następujących broszur:

Szybki przewodnik informacyjny w formacie programu Word (.docx) w formaciePDF (.pdf)

Metody regex a string

Klasa System.String zawiera kilka metod wyszukiwania i porównywania, których można używać do dopasowywania wzorca z tekstem. Na przykład metody , i określają, String.Containsczy wystąpienie ciągu zawiera określony podciąg, a String.IndexOfmetody , String.IndexOfAny, String.LastIndexOfi String.LastIndexOfAny zwracają pozycję początkową określonego podciągu w String.StartsWith ciągu. String.EndsWith Użyj metod System.String klasy podczas wyszukiwania określonego ciągu. Regex Użyj klasy podczas wyszukiwania określonego wzorca w ciągu. Aby uzyskać więcej informacji i przykładów, zobacz Wyrażenia regularne platformy .NET.

Metody statyczne a metody wystąpień

Po zdefiniowaniu wzorca wyrażenia regularnego można podać go do aparatu wyrażeń regularnych na jeden z dwóch sposobów:

  • Tworząc wystąpienie Regex obiektu reprezentującego wyrażenie regularne. W tym celu należy przekazać wzorzec wyrażenia regularnego do konstruktora Regex . Obiekt jest niezmienny. Po Regex utworzeniu wystąpienia Regex obiektu za pomocą wyrażenia regularnego nie można zmienić wyrażenia regularnego obiektu.

  • Podając zarówno wyrażenie regularne, jak i tekst do wyszukiwania w metodzie static (Shared w Visual Basic). Regex Dzięki temu można używać wyrażenia regularnego bez jawnego Regex tworzenia obiektu.

Wszystkie Regex metody identyfikacji wzorca obejmują zarówno przeciążenia statyczne, jak i wystąpienia.

Aparat wyrażeń regularnych musi skompilować określony wzorzec, zanim będzie można użyć wzorca. Ponieważ Regex obiekty są niezmienne, jest to jednorazowa procedura wykonywana po Regex wywołaniu konstruktora klasy lub metody statycznej. Aby wyeliminować konieczność wielokrotnego kompilowania pojedynczego wyrażenia regularnego, aparat wyrażeń regularnych buforuje skompilowane wyrażenia regularne używane w wywołaniach metod statycznych. W rezultacie metody dopasowywania wzorców wyrażeń regularnych oferują porównywalną wydajność dla metod statycznych i wystąpień. Jednak buforowanie może niekorzystnie wpłynąć na wydajność w następujących dwóch przypadkach:

  • W przypadku używania wywołań metod statycznych z dużą liczbą wyrażeń regularnych. Domyślnie aparat wyrażeń regularnych buforuje 15 ostatnio używanych statycznych wyrażeń regularnych. Jeśli aplikacja używa więcej niż 15 statycznych wyrażeń regularnych, niektóre wyrażenia regularne muszą być ponownie skompilowane. Aby zapobiec ponownej kompilacji, można zwiększyć Regex.CacheSize właściwość .

  • Podczas tworzenia wystąpień nowych Regex obiektów przy użyciu wyrażeń regularnych, które zostały wcześniej skompilowane. Na przykład poniższy kod definiuje wyrażenie regularne w celu zlokalizowania zduplikowanych wyrazów w strumieniu tekstowym. Mimo że w przykładzie użyto pojedynczego wyrażenia regularnego, tworzy wystąpienie nowego Regex obiektu w celu przetworzenia każdego wiersza tekstu. Spowoduje to ponowne skompilowanie wyrażenia regularnego z każdą iterację pętli.

    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()
    

    Aby zapobiec ponownej kompilacji, należy utworzyć wystąpienie pojedynczego Regex obiektu, który jest dostępny dla całego kodu, który go wymaga, jak pokazano w poniższym repisowym przykładzie.

    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()
    

Wykonywanie operacji wyrażeń regularnych

Niezależnie od tego, czy zdecydujesz się utworzyć Regex wystąpienie obiektu i wywołać jego metody, czy wywołać metody statyczne, Regex klasa oferuje następujące funkcje dopasowywania wzorców:

  • Walidacja dopasowania. Wywołaj metodę , IsMatch aby określić, czy istnieje dopasowanie.

  • Pobieranie pojedynczego dopasowania. Wywołaj metodę Match w Match celu pobrania obiektu reprezentującego pierwsze dopasowanie w ciągu lub w części ciągu. Kolejne dopasowania można pobrać, wywołując metodę Match.NextMatch .

  • Pobieranie wszystkich dopasowań. Wywołasz metodę Matches System.Text.RegularExpressions.MatchCollection , aby pobrać obiekt reprezentujący wszystkie dopasowania znalezione w ciągu lub w części ciągu.

  • Zamiana dopasowanego tekstu. Metoda jest wywoływana w celu zastąpienia dopasowanego Replace tekstu. Tekst zastępczy można również zdefiniować za pomocą wyrażenia regularnego. Ponadto niektóre Replace metody obejmują MatchEvaluator parametr, który umożliwia programowe definiowanie tekstu zastępczego.

  • Tworzenie tablicy ciągów utworzonej na podstawie części ciągu wejściowego. Metoda jest wywoływana w celu podzielenia Split ciągu wejściowego w pozycjach zdefiniowanych przez wyrażenie regularne.

Oprócz metod Regex dopasowywania wzorców klasa zawiera kilka metod specjalnego przeznaczenia:

  • Metoda Escape ucieczki od wszystkich znaków, które mogą być interpretowane jako operatory wyrażeń regularnych w wyrażeniu regularnym lub ciągu wejściowym.
  • Metoda Unescape usuwa te znaki ucieczki.
  • Metoda CompileToAssembly tworzy zestaw zawierający wstępnie zdefiniowane wyrażenia regularne. Platforma .NET zawiera przykłady tych zestawów specjalnego przeznaczenia w System.Web.RegularExpressions przestrzeni nazw.

Definiowanie wartości limitu czasu

Platforma .NET obsługuje w pełni funkcjonalny język wyrażeń regularnych, który zapewnia znaczną moc i elastyczność dopasowywania wzorców. Jednak moc i elastyczność są kosztowne: ryzyko niskiej wydajności. Wyrażenia regularne, które działają źle, są zaskakująco łatwe do utworzenia. W niektórych przypadkach operacje wyrażeń regularnych, które polegają na nadmiernym wycofywaniu, mogą przestać odpowiadać, gdy przetwarzają tekst niemal zgodny ze wzorcem wyrażenia regularnego. Aby uzyskać więcej informacji na temat aparatu wyrażeń regularnych platformy .NET, zobacz Szczegóły zachowania wyrażenia regularnego. Aby uzyskać więcej informacji na temat nadmiernego wycofywania, zobacz Wycofywanie.

Począwszy od programu .NET Framework 4.5, można zdefiniować interwał limitu czasu dla dopasowań wyrażeń regularnych w celu ograniczenia nadmiernego wycofywania. W zależności od wzorca wyrażenia regularnego i tekstu wejściowego czas wykonywania może przekraczać określony interwał limitu czasu, ale nie spędzi więcej czasu na wycofywanie niż określony interwał limitu czasu. Jeśli aparat wyrażeń regularnych upłynął, zgłasza wyjątek RegexMatchTimeoutException . W większości przypadków uniemożliwia to aparatowi wyrażeń regularnych marnowanie mocy obliczeniowej przez próbę dopasowania tekstu niemal do wzorca wyrażenia regularnego. Może to również wskazywać, że interwał limitu czasu został ustawiony zbyt nisko lub że bieżące obciążenie maszyny spowodowało ogólne obniżenie wydajności.

Sposób obsługi wyjątku zależy od przyczyny wyjątku. Jeśli wyjątek występuje, ponieważ interwał limitu czasu jest ustawiony zbyt niski lub z powodu nadmiernego obciążenia maszyny, możesz zwiększyć interwał limitu czasu i ponowić próbę dopasowania operacji. Jeśli wyjątek występuje, ponieważ wyrażenie regularne opiera się na nadmiernym wycofywaniu, można założyć, że dopasowanie nie istnieje, a opcjonalnie możesz rejestrować informacje, które pomogą zmodyfikować wzorzec wyrażenia regularnego.

Interwał limitu czasu można ustawić, wywołując Regex(String, RegexOptions, TimeSpan) konstruktor podczas tworzenia wystąpienia obiektu wyrażenia regularnego. W przypadku metod statycznych można ustawić interwał limitu czasu, wywołując przeciążenie pasującej metody, która ma matchTimeout parametr. Jeśli jawnie nie ustawisz wartości limitu czasu, domyślna wartość limitu czasu zostanie określona w następujący sposób:

  • Używając wartości limitu czasu dla całej aplikacji, jeśli istnieje. Ustaw wartość limitu czasu dla całej aplikacji, wywołując AppDomain.SetData metodę , aby przypisać reprezentację TimeSpan ciągu wartości do REGEX_DEFAULT_MATCH_TIMEOUT właściwości.
  • Używając wartości InfiniteMatchTimeout, jeśli nie ustawiono wartości limitu czasu dla całej aplikacji.

Ważne

Zalecamy ustawienie wartości limitu czasu we wszystkich operacjach dopasowywania wzorców wyrażeń regularnych. Aby uzyskać więcej informacji, zobacz Najlepsze rozwiązania dotyczące wyrażeń regularnych.

Przykłady

W poniższym przykładzie użyto wyrażenia regularnego, aby sprawdzić powtarzające się wystąpienia wyrazów w ciągu. Wyrażenie \b(?<word>\w+)\s+(\k<word>)\b regularne można interpretować, jak pokazano w poniższej tabeli.

Wzorzec opis
\b Rozpocznij dopasowanie na granicy słowa.
(?<word>\w+) Dopasuj co najmniej jeden znak słowa do granicy wyrazu. Nadaj tej przechwyconej grupie wordnazwę .
\s+ Dopasuj co najmniej jeden znak odstępu.
(\k<word>) Dopasuj przechwyconą grupę o nazwie word.
\b Dopasowuje granicę wyrazu.
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

W następnym przykładzie pokazano użycie wyrażenia regularnego w celu sprawdzenia, czy ciąg reprezentuje wartość waluty, czy ma poprawny format reprezentujący wartość waluty. W tym przypadku wyrażenie regularne jest tworzone dynamicznie na podstawie NumberFormatInfo.CurrencyDecimalSeparatorwłaściwości , CurrencyDecimalDigits, NumberFormatInfo.CurrencySymbol, NumberFormatInfo.NegativeSigni NumberFormatInfo.PositiveSign dla kultury en-US. Wynikowe wyrażenie regularne to ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$. To wyrażenie regularne można interpretować, jak pokazano w poniższej tabeli.

Wzorzec opis
^ Zacznij od początku ciągu.
\s* Dopasowanie do zera lub większej liczby znaków odstępu.
[\+-]? Dopasowuje zero lub jedno wystąpienie znaku dodatniego lub znaku ujemnego.
\s? Dopasowuje zero lub jeden znak odstępu.
\$? Dopasuj zero lub jedno wystąpienie znaku dolara.
\s? Dopasowuje zero lub jeden znak odstępu.
\d* Dopasowanie do zera lub większej liczby cyfr dziesiętnych.
\.? Dopasuj symbol zero lub jeden punkt dziesiętny.
(\d{2})? Przechwytywanie grupy 1: Dopasuj dwie cyfry dziesiętne zero lub jeden raz.
(\d*\.?(\d{2})?){1} Dopasuj wzorzec cyfr całkowitych i ułamkowych rozdzielonych symbolem separatora dziesiętnego dokładnie raz.
$ Dopasuj koniec ciągu.

W tym przypadku wyrażenie regularne zakłada, że prawidłowy ciąg waluty nie zawiera symboli separatora grupy i że nie zawiera cyfr ułamkowych ani liczby cyfr ułamkowych zdefiniowanych przez właściwość określonej kultury 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.

Ponieważ wyrażenie regularne w tym przykładzie jest tworzone dynamicznie, nie wiesz w czasie projektowania, czy symbol waluty, znak dziesiętny lub pozytywne i ujemne oznaki określonej kultury (en-US w tym przykładzie) mogą być błędnie interpretowane przez aparat wyrażeń regularnych jako operatory języka wyrażeń regularnych. Aby zapobiec błędnej interpretacji, przykład przekazuje każdy dynamicznie wygenerowany ciąg do Escape metody .