Регулярные выражения в .NET Framework
Регулярные выражения предоставляют мощный, гибкий и эффективный метод обработки текста. Обширные возможности сопоставления шаблонов, предоставляемые регулярными выражениями, позволяют быстро анализировать большие объемы текста, отыскивая в них определенные символьные шаблоны, проверять текст на соответствие определенным заранее шаблонам (например, формату адреса электронной почты), извлекать, изменять, заменять или удалять подстроки текста, а также добавлять извлеченные строки в коллекцию для формирования отчетов. Регулярные выражения — это незаменимый инструмент для многих приложений, в которых ведется работа со строками или анализ объемных блоков текста.
Как работают регулярные выражения
Основа обработки текста с помощью регулярных выражений — это подсистема обработки регулярных выражений, представленная в платформе .NET Framework объектом System.Text.RegularExpressions.Regex. Минимальный набор сведений, который требуется предоставить подсистеме обработки регулярных выражений для обработки текста с помощью регулярных выражений, сводится к двум вещам.
Шаблон регулярного выражения, который требуется найти в тексте.
В платформе .NET Framework шаблоны регулярных выражений определяются с использованием особого синтаксиса или языка, совместимого с регулярными выражениями Perl 5 и обладающего некоторыми дополнительными возможностями (например, он поддерживает сопоставление справа налево). Дополнительные сведения см. в разделе Элементы языка регулярных выражений.
Текст, который требуется проанализировать с помощью шаблона регулярного выражения.
Методы класса Regex позволяют выполнять следующие действия:
Определить, встречается ли во входном тексте шаблон регулярного выражения, можно путем вызова метода IsMatch. Пример использования метода IsMatch для проверки текста см. в разделе Практическое руководство. Проверка строк на соответствие формату электронной почты.
Извлечь из текста одно или все вхождения, соответствующие шаблону регулярного выражения, можно путем вызова метода Match или Matches. Первый метод возвращает объект Match, предоставляющий сведения о совпадении в тексте. Второй метод возвращает коллекцию MatchCollection, в которую входят объекты Match для всех совпадений, найденных в проанализированном тексте.
Заменить текст, соответствующий шаблону регулярного выражения, можно путем вызова метода Replace. Примеры использования метода Replace для изменения формата даты и удаления недопустимых символов из строки см. в разделах Практическое руководство. Исключение недопустимых символов из строки и Пример. Изменение форматов даты.
Общие сведения об объектной модели регулярных выражений см. в разделе Объектная модель регулярных выражений.
Примеры регулярных выражений
В классе String имеется ряд работающих со строками методов поиска и замены, которые можно использовать для поиска строк-литералов в более крупных строках. Регулярные выражения наиболее полезны, если требуется найти в крупной строке одну или несколько подстрок или выявить шаблоны в строке, как показано в следующих примерах.
Пример 1. Замена подстрок
Предположим, список рассылки содержит записи, в которых, помимо имени и фамилии, может указываться обращение ("Mr.", "Mrs.", "Miss" или "Ms."). Если при создании меток для конвертов по такому списку указывать обращение не требуется, можно использовать для удаления обращений регулярное выражение, как показано в следующем примере.
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
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
Шаблон регулярного выражения (Mr\.? |Mrs\.? |Miss |Ms\.? ) совпадает с любым вхождением "Mr ", "Mr. " , "Mrs ", "Mrs. " , "Miss ", "Ms или "Ms. " . Вызов метода Regex.Replace приведет к замене найденных при сопоставлении подстрок на String.Empty; другими словами, найденная подстрока удаляется из исходной строки.
Пример 2. Определение повторяющихся слов
Случайное повторение слов — частая ошибка писателей. Для выявления повторяющихся слов можно использовать регулярное выражение, как показано в следующем примере.
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
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
Шаблон регулярного выражения \b(\w+?)\s\1\b можно интерпретировать следующим образом:
\b |
Начало на границе слова. |
(\w+) |
Совпадение с одним или несколькими символами слова. Вместе они формируют группу, на которую можно сослаться, указав обозначение \1. |
\s |
Соответствует пробелу. |
\1 |
Соответствует подстроке, совпадающей с группой \1. |
\b |
Соответствует границе слова. |
При вызове метода Regex.Matches параметры регулярного выражения заданы как RegexOptions.IgnoreCase. Это значит, что операция сопоставления не будет учитывать регистр и код в примере будет считать подстроку "This this" повторяющейся.
Обратите внимание, что входная строка содержит подстроку "this. This". Тем не менее из-за разделяющего знака пунктуации повторением это не считается.
Пример 3. Динамическое построение регулярного выражения, учитывающего язык и региональные параметры
В следующем примере демонстрируется мощь регулярных выражений в сочетании с гибкостью, обеспечиваемой компонентами глобализации платформы .NET Framework. В примере объект NumberFormatInfo используется с целью определения формата значений валюты для текущего языка и региональных параметров. Затем полученные сведения используются для динамического формирования регулярного выражения, выделяющего в тексте значения валюты. Для каждого совпадения выделяется подгруппа, содержащая числовую строку, которая затем преобразуется в значение типа Decimal, после чего вычисляется нарастающий итог.
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.
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.
На компьютере, где в качестве языка и региональных параметров задано значение "Английский - США" (en-US), в примере будет динамически сформировано регулярное выражение \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?). Этот шаблон регулярного выражения можно интерпретировать следующим образом:
\$ |
Поиск одиночного вхождения символа доллара ("$") во входной строке. Строка шаблона регулярного выражения содержит обратную косую черту, указывающую на то, что символ доллара следует интерпретировать как литерал, а не как привязку регулярного выражения. (Сам по себе символ "$" означает, что подсистема обработки регулярных выражений должна искать начало совпадения в конце строки.) Чтобы гарантировать, что символ валюты для текущего языка и региональных параметров не будет принят за символ регулярного выражения, в примере вызывается метод Escape, выполняющий нужное escape-преобразование символа. |
\s* |
Поиск вхождения пробелов числом от нуля и выше. |
[-+]? |
Поиск вхождения положительного или отрицательного знака числом от нуля до единицы. |
([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?) |
Круглые скобки, в которые заключено это выражение, указывают на то, что это группа записи или часть выражения. При обнаружении совпадения сведения об этой части совпадающей строки можно будет извлечь из второго объекта Group в коллекции GroupCollection, возвращаемой свойством Match.Groups. (Первый элемент коллекции представляет все совпадение целиком.) |
[0-9]{0,3} |
Поиск вхождений десятичных цифр от 0 до 9 числом от нуля до трех. |
(,[0-9]{3})* |
Поиск вхождений разделителя групп, за которым следуют три десятичные цифры, числом от нуля и выше. |
\. |
Поиск одиночного вхождения разделителя целой и дробной частей. |
[0-9]+ |
Поиск одной или нескольких десятичных цифр. |
(\.[0-9]+)? |
Поиск вхождений разделителя целой и дробной частей, за которым следует по меньшей мере одна десятичная цифра, числом от нуля до единицы. |
При обнаружении всех этих вложенных шаблонов во входной строке совпадение считается успешным, и к объекту MatchCollection добавляется объект Match, содержащий сведения о данном совпадении.
Связанные разделы
Заголовок |
Описание |
---|---|
Сведения о символах, операторах и конструкциях, используемых для определения регулярных выражений. |
|
Рекомендации по использованию регулярных выражений в .NET Framework |
Рекомендации по оптимизации производительности регулярных выражений и созданию надежных шаблонов регулярных выражений. |
Сведения и примеры кода, в которых описывается использование классов регулярных выражений. |
|
Содержит сведения о возможностях и поведении регулярных выражений .NET Framework. |
|
Примеры кода, в которых демонстрируются типичные способы применения регулярных выражений. |