TOC

This article has been localized into Russian by the community.

Стандартные Выражения (Regex):

Поиск с Regex Class

Как мы уже говорили в предыдущей статье, регулярные выражения позволяют определять шаблоны поиска для работы со строками. Чтобы обработать этот шаблон поиска, .NET framework поставляется с очень универсальным классом: класс Regex. В этой статье мы определим некоторые шаблоны поиска и используем их с классом Regex, но, пожалуйста, имейте в виду, что синтаксис регулярных выражений может быть довольно сложным и что это учебник по C#, а не учебник по регулярным выражениям. Вместо этого, я буду использовать некоторые простые регулярные выражения, чтобы показать, как вы работаете с ними в C#. Если вы хотите узнать больше о регулярном выражении, я могу порекомендовать этот Regular Expression Tutorial.

Метод IsMatch()

В этом первом примере я буду использовать один из самых простых методов класса Regex-IsMatch. Он просто возвращает true или false, в зависимости от того, есть ли одно или несколько совпадений в тестовой строке:

string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
if (regex.IsMatch(testString))
    Console.WriteLine("String contains numbers!");
else
    Console.WriteLine("String does NOT contain numbers!");

Мы определяем тестовую строку, а затем создаем экземпляр класса Regex. Мы передаем фактическое регулярное выражение в виде строки - в этом случае регулярное выражение указывает, что мы ищем число любой длины. Затем мы выводим строку текста в зависимости от того, совпадает ли регулярное выражение с нашей тестовой строкой. Довольно круто, но в большинстве случаев вы хотите что - то сделать с математическими выражениями - для этого у нас есть Match class.

Match Class & метод

В следующем примере мы возьмем число, находящееся в тестовой строке, и представим его пользователю, а не просто проверим, что оно там есть:

string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Number found: " + match.Value);

Мы используем тот же regex и тестовой строкой, как раньше. Я вызываю методMatch () , который возвращает экземпляр класса Match - это произойдет независимо от того, действительно ли найдено совпадение. Чтобы убедиться, что найдено соответствие есть, я проверяю свойство Success. Как только я уверен, что соответствие найдено, я использую свойство Value для его получения.

Класс Match содержит больше полезной информации, чем просто сопоставленная строка - например, вы можете легко узнать, где было найдено соответствие, его длину и так далее:

string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Match found at index " + match.Index + ". Length: " + match.Length);

Здесь Index и Length использованы для отображения информации о месте и длине математического значения.

Анализируемые группы

В первых двух примерах мы нашли только одно значение в строке поиска, но регулярные выражения могут, конечно, сделать гораздо больше! Например, мы можем найти и имя, и возраст в нашей тестовой строке, сортируя ненужные вещи, такие как команда и текст "лет". Делать подобные вещи-это кусок пирога для регулярных выражений, но если вы не знакомы с синтаксисом, это может показаться очень сложным, но давайте все равно попробуем:

string testString = "John Doe, 42 years";
Regex regex = new Regex(@"^([^,]+),\s([0-9]+)");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Name: " + match.Groups[1].Value + ". Age: " + match.Groups[2].Value);

Я изменил регулярное выражение так, что оно ищет все, что не является запятой - это значение помещается в первую группу захвата, благодаря окружающим скобкам. Затем он ищет разделяющую запятую и после этого число, которое помещается во вторую анализируемую группу (опять же, благодаря окружающим скобкам). В последней строке я использую свойство Groups для доступа к сопоставленным группам. Я использую индекс 1 для имени и 2 для возраста, так как он соответствует порядку, в котором группы соответствий были определены в строке регулярного выражения (индекс 0 содержит все совпадение).

Именованные анализируемые группы

Как только регулярное выражение становится более продвинутым/более длинным, чем мы только что использовали, пронумерованные группы анализа могут стать неуправляемыми, потому что вам постоянно нужно помнить их порядок и индекс. К счастью для нас, регулярные выражения и .NET framework поддерживают именованные группы, что позволит вам дать имя каждой из групп в регулярном выражении, а затем ссылаться на него в свойстве Groups. Посмотрите этот переписанный пример, где мы используем именованные группы вместо нумерованных:

string testString = "John Doe, 42 years";
Regex regex = new Regex(@"^(?<name>[^,]+),\s(?<age>[0-9]+)");
Match match = regex.Match(testString);
if (match.Success)
    Console.WriteLine("Name: " + match.Groups["name"].Value + ". Age: " + match.Groups["age"].Value);

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

Класс MatchCollection

Класс Match подходит, если вы хотите работать только с одним совпадением (помните, что совпадение может содержать несколько значений, как мы видели в предыдущих примерах), но иногда вы хотите работать сразу с несколькими совпадениями. Для этого у нас есть метод Matches(), который вернет класс MatchCollection. Он будет содержать все соответствующее содержимое, в том порядке, в котором оно находится. Давайте посмотрим, как его можно использовать:

string testString = "123-456-789-0";
Regex regex = new Regex(@"([0-9]+)");
MatchCollection matchCollection = regex.Matches(testString);
foreach (Match match in matchCollection)
    Console.WriteLine("Number found at index " + match.Index + ": " + match.Value);

Я изменил регулярное выражение и тестовую строку по сравнению с предыдущими примерами. Теперь у нас есть тестовая строка, которая содержит несколько чисел и регулярное выражение, которое специально ищет строки, состоящие из одного или нескольких чисел. Мы используем метод Matches () , чтобы получить MatchCollection из нашего регулярного выражения, которое содержит совпадения, найденные в строке. В этом случае есть четыре совпадения, которые мы выводим одно за другим с помощью цикла foreach. Результат будет выглядеть примерно так:

Number found at index 0: 123
Number found at index 4: 456
Number found at index 8: 789
Number found at index 12: 0

Если совпадения найдены не будут, будет выведен пустой MatchCollection.

Резюме

С помощью класса Regex, наряду с классами Match и MatchCollection, мы можем легко выполнить очень расширенное сопоставление строк. Синтаксис регулярных выражений может показаться очень сложным, но как только вы его изучите, у вас будет очень сильный инструмент. Даже если вы не хотите тратить время на изучение синтаксиса регулярных выражений, вы часто можете найти выражения для конкретных потребностей, созданные другими программистами, с помощью простого поиска Google. Как только вы написали или позаимствовали строку regex, вы можете использовать ее для своих целей с методами и классами, продемонстрированными в этой статье.

Но поиск это только часть пользы - вы также можете сделать некоторые очень интересные операции поиска/замены регулярными выражениями. Мы рассмотрим это в одной из следующих статей.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!