Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
Класс Regex представляет движок регулярных выражений .NET. Этот класс можно использовать для:
- Быстрый анализ больших объемов текста для поиска определенных шаблонов символов.
- извлечение, изменение, замена или удаление текстовых подстрок;
- Добавьте извлеченные строки в коллекцию для создания отчета.
Примечание.
Если вы хотите проверить строку, определив, соответствует ли она определенному шаблону регулярного выражения, можно использовать System.Configuration.RegexStringValidator класс.
Чтобы использовать регулярные выражения, вы определяете шаблон, который необходимо определить в текстовом потоке с помощью синтаксиса, документированного на языке регулярных выражений, — быстрая ссылка. Затем можно опционально создать экземпляр объекта Regex. Наконец, вызывается метод, выполняющий некоторые операции, например замена текста, соответствующего шаблону регулярного выражения, или определение соответствия шаблона.
Дополнительные сведения о языке регулярных выражений см. в разделе "Язык регулярных выражений" — краткий справочник или скачивание и печать одного из этих брошюр:
Краткий справочник в формате Word (.docx)Краткий справочник в формате PDF (.pdf)
Методы Regex и String
Класс System.String включает несколько методов поиска и сравнения, которые можно использовать для выполнения сопоставления шаблонов с текстом. Например, методы String.Contains, String.EndsWith и String.StartsWith определяют, содержит ли строковый экземпляр указанную подстроку; а методы String.IndexOf, String.IndexOfAny, String.LastIndexOf и 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($"{input} ({matches.Count} matches):"); 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($"{input} ({matches.Count} matches):"); 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
можно интерпретировать, как показано в следующей таблице.
Расписание | Описание |
---|---|
\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($"{matches.Count} matches found in:\n {text}");
// Report on each match.
foreach (Match match in matches)
{
GroupCollection groups = match.Groups;
Console.WriteLine($"'{groups["word"].Value}' repeated at positions {groups[0].Index} and {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, CurrencyDecimalDigits, NumberFormatInfo.CurrencySymbol, NumberFormatInfo.NegativeSign и NumberFormatInfo.PositiveSign для культуры en-US. Результирующее регулярное выражение ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$
. Это регулярное выражение можно интерпретировать, как показано в следующей таблице.
Расписание | Описание |
---|---|
^ |
Начните с начала строки. |
\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 метод.