Классы библиотеки.NET для работы с регулярными выражениями объединены в пространство имен System.Text.RegularExpressions.
Начнем с класса Regex, представляющего собственно регулярное выражение. Класс является неизменяемым, то есть после создания экземпляра его корректировка не допускается. Для описания регулярного выражения в классе определено несколько перегруженных конструкторов:
□ Regex () — создает пустое выражение;
□ Regex (String) — создает заданное выражение;
□ Regex(String, RegexOptions) — создает заданное выражение и задает параметры
для его обработки с помощью элементов перечисления RegexOptions (напри
мер, различать или не различать прописные и строчные буквы).
Пример конструктора, задающего выражение для поиска в тексте повторяющихся слов, расположенных подряд и разделенных произвольным количеством пробелов, независимо от регистра:
Regex rх = new Regex(@"\b(?<word>\w+)\s+(\k<word>)\b". RegexOptions.IgnoreCase);
Поиск фрагментов строки, соответствующих заданному выражению, выполняется с помощью методов IsMatch, Match и Matches.
|
|
Метод IsMatch возвращает true, если фрагмент, соответствующий выражению, в заданной строке найден, и false в противном случае. В листинге 15.3 приведен пример поиска повторяющихся слов в двух тестовых строках. В регулярное выражение, приведенное ранее, добавлен фрагмент, позволяющий распознавать знаки препинания.
Листинг 15.3. Поиск в строке дублированных слов (методом IsMatch)
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
Regex r = new Regex(@"\b(?<word>\w+)[.,:;!? ]\s*(\k<word>)\b",
RegexOptions.IgnoreCase);
string tst1 = "Oh. oh! Give me more!";
if (r.IsMatch(tst1)) Console.WriteLine(" tst1 yes");
else Console.WriteLine(" tst1 no");
string tst2 = "Oh give me. give me more!";
if (r.IsMatch(tst2)) Console.WriteLine(" tst2 yes");
else Console.WriteLine(" tst2 no");
}
}
Результат работы программы:
tst1 yes
tst2 no
Повторяющиеся слова в строке tst2 располагаются не подряд, поэтому она не соответствует регулярному выражению. Для поиска повторяющихся слов, расположенных в произвольных позициях строки, в регулярном выражении нужно всего-навсего заменить пробел (\s) «любым символом» (.):
Regex r = new Regex(@"\b(?<word>\w+)[..:;!? ].*(\k<word>)\b". RegexOptions.IgnoreCase);
Метод Match класса Regex, в отличие от метода IsMatch, не просто определяет, произошло ли совпадение, а возвращает объект класса Match — очередной фрагмент, совпавший с образцом. Рассмотрим листинг 15.4, в котором используется этот метод.
Листинг 15.4. Выделение из строки слов и чисел (методом Match)
public class Test
{
public static void Main()
{
string text = "Салат - $4. борщ - $3. одеколон - $10.";
string pattern = @"(\w+) - \$(\d+)[.,]";
Regex r = new Regex(pattern);
Match m = r.Match(text);
int total = 0;
while (m.Success)
{
Console.WriteLine(m);
total += int.Parse(m.Groups[2].ToString());
m = m.NextMatch();
|
|
}
Console.WriteLine("Итого: $" + total);
}
}
Результат работы программы:
Салат - $4.
борщ - $3.
одеколон - $10.
Итого: $17
При первом обращении к методу Match возвращается первый фрагмент строки, совпавший с регулярным выражением pattern. В классе Match определено свойство Groups, возвращающее коллекцию фрагментов, совпавших с подвыражениями в круглых скобках. Нулевой элемент коллекции содержит весь фрагмент, первый элемент — фрагмент, совпавший с подвыражением в первых скобках, второй элемент — фрагмент, совпавший с подвыражением во вторых скобках, и т. д. Если при определении выражения задать фрагментам имена, как это было
сделано в предыдущем листинге, можно будет обратиться к ним по этим именам, например:
string pattern = @"(?'name'\w+) - \$(?'price'\d+)[..]";
total += int.Parse(m. Groups ["price"].ToString());