Класс System.Text.RegularExpressions.Regex

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Класс Regex представляет . Подсистема регулярных выражений NET. Этот класс можно использовать для:

  • Быстрый анализ больших объемов текста для поиска определенных шаблонов символов.
  • извлечение, изменение, замена или удаление текстовых подстрок;
  • Добавьте извлеченные строки в коллекцию для создания отчета.

Примечание.

Если вы хотите проверить строку, определив, соответствует ли она определенному шаблону регулярного выражения, можно использовать System.Configuration.RegexStringValidator класс.

Чтобы использовать регулярные выражения, вы определяете шаблон, который необходимо определить в текстовом потоке с помощью синтаксиса, документированного на языке регулярных выражений, — быстрая ссылка. Затем можно создать Regex экземпляр объекта. Наконец, вызывается метод, выполняющий некоторые операции, например замена текста, соответствующего шаблону регулярного выражения, или определение соответствия шаблона.

Дополнительные сведения о языке регулярных выражений см. в разделе "Язык регулярных выражений" — краткий справочник или скачивание и печать одного из этих брошюр:

Краткий справочник по форматуWord (.docx) в формате PDF (.pdf)

Методы Regex и String

Класс System.String включает несколько методов поиска и сравнения, которые можно использовать для выполнения сопоставления шаблонов с текстом. Например, методы и String.StartsWith методы определяют, String.ContainsString.EndsWithсодержит ли строковый экземпляр указанную подстроку; и методы , String.LastIndexOfа String.IndexOfString.IndexOfAnyтакже String.LastIndexOfAny методы возвращают начальную позицию указанной подстроки в строке. Используйте методы класса при поиске определенной System.String строки. Regex Используйте класс при поиске определенного шаблона в строке. Дополнительные сведения и примеры см. в разделе регулярных выражений .NET.

Статические методы и методы экземпляра

После определения шаблона регулярного выражения его можно предоставить обработчику регулярных выражений двумя способами:

  • Создав Regex экземпляр объекта, представляющего регулярное выражение. Для этого вы передаете шаблон регулярного выражения конструктору Regex . Regex Объект неизменяем; при создании экземпляра Regex объекта с регулярным выражением не может быть изменено регулярное выражение этого объекта.

  • Указав регулярное выражение и текст для поиска static в методе (Sharedв Visual Basic). Regex Это позволяет использовать регулярное выражение без явного Regex создания объекта.

Все Regex методы идентификации шаблонов включают как статические, так и экземплярные перегрузки.

Обработчик регулярных выражений должен скомпилировать определенный шаблон, прежде чем можно будет использовать шаблон. Так как Regex объекты неизменяемы, это одноразовая процедура, которая возникает при Regex вызове конструктора класса или статического метода. Чтобы исключить необходимость многократной компиляции одного регулярного выражения, подсистема регулярных выражений кэширует скомпилированные регулярные выражения, используемые в вызовах статических методов. В результате методы сопоставления шаблонов регулярного выражения обеспечивают сравнимую производительность для статических и экземплярных методов. Однако кэширование может негативно повлиять на производительность в следующих двух случаях:

  • При использовании вызовов статических методов с большим количеством регулярных выражений. По умолчанию обработчик регулярных выражений кэширует 15 последних статических регулярных выражений. Если приложение использует более 15 статических регулярных выражений, необходимо перекомпилировать некоторые регулярные выражения. Чтобы предотвратить повторную Regex.CacheSize компиляцию, можно увеличить свойство.

  • При создании экземпляров новых Regex объектов с регулярными выражениями, которые ранее были скомпилированы. Например, следующий код определяет регулярное выражение для поиска повторяющихся слов в текстовом потоке. Хотя в примере используется одно регулярное выражение, он создает экземпляр нового Regex объекта для обработки каждой строки текста. Это приводит к перекомпиляции регулярного выражения с каждой итерацией цикла.

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

    Чтобы предотвратить повторную компиляцию, необходимо создать экземпляр одного Regex объекта, доступного для всего кода, который требует его, как показано в следующем примере перезаписи.

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

Выполнение операций регулярного выражения

Если вы решите создать Regex экземпляр объекта и вызвать его методы или вызвать статические методы, Regex класс предлагает следующие функции сопоставления шаблонов:

  • Проверка соответствия. IsMatch Вызывается метод, чтобы определить, присутствует ли совпадение.

  • Получение одного совпадения. Метод вызывается Match для получения Match объекта, представляющего первое совпадение в строке или в части строки. Последующие совпадения можно получить путем вызова Match.NextMatch метода.

  • Получение всех совпадений. Метод вызывается Matches для получения System.Text.RegularExpressions.MatchCollection объекта, представляющего все совпадения, найденные в строке или в части строки.

  • Замена соответствующего текста. Метод вызывается Replace для замены соответствующего текста. Замещающий текст также можно определить регулярным выражением. Кроме того, некоторые методы Replace включают MatchEvaluator параметр, позволяющий программно определить замещающий текст.

  • Создание массива строк, сформированного из частей входной строки. Метод вызывается Split для разделения входной строки по позициям, определенным регулярным выражением.

Помимо методов сопоставления шаблонов Regex класс включает несколько методов специального назначения:

  • Метод Escape экранирует все символы, которые могут интерпретироваться как операторы регулярных выражений в регулярном выражении или входной строке.
  • Метод Unescape удаляет эти escape-символы.
  • Метод CompileToAssembly создает сборку, содержащую предопределенные регулярные выражения. .NET содержит примеры этих сборок специального назначения в System.Web.RegularExpressions пространстве имен.

Определение значения времени ожидания

.NET поддерживает полнофункциональный язык регулярных выражений, обеспечивающий значительную мощность и гибкость в сопоставлении шаблонов. Тем не менее, мощность и гибкость приходят по стоимости: риск плохой производительности. Регулярные выражения, которые выполняются плохо, удивительно легко создавать. В некоторых случаях операции регулярного выражения, использующие чрезмерную обратную дорожку, могут перестать отвечать при обработке текста, который почти соответствует шаблону регулярного выражения. Дополнительные сведения о обработчике регулярных выражений .NET см. в разделе "Сведения о поведении регулярных выражений". Дополнительные сведения о чрезмерной обратной дорожке см. в разделе Backtracking.

Начиная с платформа .NET Framework 4.5, можно определить интервал времени ожидания для совпадений регулярных выражений, чтобы ограничить чрезмерное обратное отслеживание. В зависимости от шаблона регулярного выражения и входного текста время выполнения может превышать указанный интервал времени ожидания, но он не будет тратить больше времени обратного отслеживания, чем указанный интервал времени ожидания. Если время ожидания обработчика регулярных выражений истекает RegexMatchTimeoutException , создается исключение. В большинстве случаев это позволяет обработчику регулярных выражений не тратить мощность обработки, пытаясь сопоставить текст, который почти соответствует шаблону регулярного выражения. Однако это также может указывать на то, что интервал времени ожидания был установлен слишком низким или что текущая загрузка компьютера вызвала общее снижение производительности.

Обработка исключения зависит от причины исключения. Если исключение возникает из-за слишком низкого интервала времени ожидания или из-за чрезмерной нагрузки компьютера, можно увеличить интервал времени ожидания и повторить операцию сопоставления. Если исключение возникает из-за того, что регулярное выражение использует чрезмерное обратное отслеживание, можно предположить, что совпадение не существует, и, при необходимости, можно записать сведения, которые помогут изменить шаблон регулярного выражения.

Вы можете задать интервал времени ожидания, вызвав Regex(String, RegexOptions, TimeSpan) конструктор при создании экземпляра объекта регулярного выражения. Для статических методов можно задать интервал времени ожидания, вызвав перегрузку соответствующего метода, имеющего matchTimeout параметр. Если значение времени ожидания явно не задано, значение времени ожидания по умолчанию определяется следующим образом:

  • При наличии значения времени ожидания на уровне приложения. Задайте значение времени ожидания приложения, вызвав AppDomain.SetData метод, чтобы назначить строковое представление TimeSpan значения свойству REGEX_DEFAULT_MATCH_TIMEOUT .
  • Если значение InfiniteMatchTimeoutвремени ожидания приложения не задано.

Внимание

Рекомендуется задать значение времени ожидания во всех операциях сопоставления шаблонов регулярных выражений. Дополнительные сведения см. в рекомендациях по регулярным выражениям.

Примеры

В следующем примере регулярное выражение используется для проверка для повторяющихся вхождения слов в строке. Регулярное выражение \b(?<word>\w+)\s+(\k<word>)\b можно интерпретировать, как показано в следующей таблице.

Расписание Description
\b Запустите совпадение на границе слова.
(?<word>\w+) Соответствует одному или нескольким символам слова до границы слова. Назовите эту захваченную группу word.
\s+ Совпадение с одним или несколькими пробелами.
(\k<word>) Соответствует записанной группе, которая называется word.
\b Соответствует границе слова.
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

В следующем примере показано использование регулярного выражения для проверка, представляет ли строка значение валюты или имеет правильный формат для представления значения валюты. В этом случае регулярное выражение создается динамически из NumberFormatInfo.CurrencyDecimalSeparatorязыка и NumberFormatInfo.NegativeSignCurrencyDecimalDigitsNumberFormatInfo.CurrencySymbolрегиональных параметров , а также NumberFormatInfo.PositiveSign свойств для языка и региональных параметров en-US. Результирующее регулярное выражение ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$. Это регулярное выражение можно интерпретировать, как показано в следующей таблице.

Расписание Description
^ Начните с начала строки.
\s* Соответствует нулю или нескольким символам пробела.
[\+-]? Соответствует нулю или одному вхождения положительного знака или отрицательного знака.
\s? Совпадение с нулем или одним символом пробела.
\$? Соответствует нулю или одному вхождения знака доллара.
\s? Совпадение с нулем или одним символом пробела.
\d* Соответствует нулю или нескольким десятичным числам.
\.? Соответствует нулю или одному символу десятичной запятой.
(\d{2})? Запись группы 1. Сопоставление двух десятичных цифр ноль или один раз.
(\d*\.?(\d{2})?){1} Соответствует шаблону целочисленных и дробных цифр, разделенных десятичным символом по крайней мере один раз.
$ Соответствует концу строки.

В этом случае регулярное выражение предполагает, что допустимая строка валюты не содержит символы разделителя групп, и что она не имеет дробных цифр или количество дробных цифр, определенных свойством указанного языка и региональных 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.

Так как регулярное выражение в этом примере создается динамически, во время разработки не известно, является ли символ валюты, десятичный знак или положительные и отрицательные признаки указанного языка и региональных параметров (en-US в этом примере) неправильно интерпретируются обработчиком регулярных выражений как операторы языка регулярного выражения. Чтобы предотвратить неправильное понимание, в примере передается каждая динамически созданная строка в Escape метод.