Регулярные выражения
Регулярное выражение – это некий шаблон, составленный из символов и спецсимволов, который позволяет находить подстроки соответствующие этому шаблону в других строках.
Классы, предназначенные для работы с регулярными выражениями, содержатся в сборке System.dll и описаны в пространстве имен System.Text.RegularExpressions. Основным классом, обеспечивающим реализацию всех действий, связанных с использованием регулярных выражений (поиск, замена, разбиение строки), является класс Regex. Все прочие классы являются вспомогательными, и используются при описании параметров методов класса Regex или их возвращаемых значений.
Класс Regex имеет конструктор, который принимает регулярное выражение:
Regex regex = new Regex(pattern);Здесь
pattern
- строка, содержащая регулярное выражение. Описание класса со всеми вариантами конструктора.Для обработки строк с помощью регулярных выражений не обязательно создавать экземпляры класса Regex; вместо этого можно использовать статические методы данного класса.
Методы класса Regex
Все основные методы класса Regex реализованы в двух вариантах: статическом и экземплярном; при этом каждый из вариантов реализован для нескольких наборов параметров. Имеется шесть основных методов:IsMatch
(типаbool
) - возвращает True, если требуемое выражение найдено, и False в противном случае;Match
(типаMatch
) - возвращает первое найденное выражение;Matches
(типаMatchCollection
) - возвращает все найденные выражения;Split
(типа string[]) - разбивает строку на фрагменты; разделители фрагментов определяются регулярным выражением;Replace
(типаstring
) - заменяет найденные выражения.
Проверка на соответствие сроки формату
Задача: определить, является ли заданная строка ростовским городским телефонным номером в федеральном формате (формат номера:+7 (863) 2**-**-**
или +7 (863) 3**-**-**
). Такая задача может быть решена в виде следующей функции:
static bool IsPhoneNo(string input)
{
Regex regex = new Regex(@"^\+7\s*\(863\)\s*[23]\d{2}-\d{2}-\d{2}$");
return regex.IsMatch(input);
}
или (если использовать статический метод)
static bool IsPhoneNo(string input) =>
Regex.IsMatch(input, @"^\+7\s*\(863\)\s*[23]\d{2}-\d{2}-\d{2}$");
Здесь перед началом строки регулярного выражения стоит символ «@» который указывает компилятору воспринимать все символы буквально. Это необходимо, чтобы корректно воспринимался символ «\».
Использование Match
Задача: найти в строке первое слово, которое начинается с буквы 'a'static string FirstWordStartingWithA(string input) { var match = Regex.Match(input, @"\ba\w*\b", RegexOptions.IgnoreCase); return match.Value; }
Метод Match
возвращает значение класса Match
. Value
- свойство класса, которое соответствует найденной подстроке. Прочие свойства класса Match
.
Поиск в строке всех вхождений регулярного выражения
Задача: Дана строка, содержащая слова, знаки пунктуации и числа в десятичной системе счисления. Сформировать последовательность строк, содержащий все строковые представления чисел из исходной строки в том же порядке.static IEnumerable<string> AllNumbers(string input) => Regex.Matches(input, @"\b\d+\b").Select(x => x.Value);Метод
Match
возвращает значение класса MatchCollection
. Элементы MatchCollection
можно перебрать в цикле
var s = "red green gray blue"; foreach (Match m in Regex.Matches(s,@"\w+")) WriteLine($"{m.Value} {m.Index}");
Разбиение строки на фрагменты
Задача: Дана строка, содержащая слова, разделённые одним или несколькими пробелами. Сформировать последовательность строк, содержащий все слова из исходной строки в том же порядке.static string[] WordsInString(string input) => Regex.Split(input, @"\s+");
Группирование и ссылки на группы
С помощью круглых скобок можно формировать группы регулярного выражения, на которые в дальнейшем можно ссылаться по номеру или по имени:(expr)
- включить соответствие для выражения expr в нумерованную группу (группы нумеруются от 1 согласно порядку следования их открывающих скобок; группа 0 соответствует всему найденному вхождению);-
(?<name>expr)
или(?'name'expr)
- включить соответствие для выражения expr в именованную группу с именем name; -
(?:expr)
- группирующее выражение, не связываемое с нумерованной или именованной группой; \N
- ссылка на ранее найденную группу с номером N, означающая, что в данной позиции регулярного выражения должен содержаться текст этой группы;\k
- ссылка на группу с именем nаme.
Задача: Написать функцию, которая по заданному телефонному номеру в федеральном формате (+7 (код_города) городской_номер
) возвращает городской телефонный номер. Считать, что код города может состоять из трёх или четырёх цифр. Если исходная строка не соответствует заданному формату, возвращать пустую строку.
static string CityNum(string input) =>
Regex.Match(input, @"\+7\s*\(\d{3,4}\)\s*(\d{2,3}\-\d{2}\-\d{2})")
.Groups[1].Value;
Замены при помощи регулярных выражений
В выражениях замены используются управляющие последовательности (подстановки), отличные от директив языка регулярных выражений. Ниже приводятся наиболее часто используемые подстановки:
- $$ - символ $;
- $0 - все найденное вхождение;
- $_ - вся исходная строка;
- $N - найденная группа с номером N (или пустая строка, если группа не найдена);
- ${name} - найденная группа с именем name (или пустая строка, если группа не найдена).
var s = "Взять все слова в угловые скобки"; s = Regex.Replace(s,@"\b\w+\b", "<$0>"); Console.WriteLine(s);В случае сложных видов замены используется вариант метода Replace с параметром-делегатом MatchEvaluator.
var s = "Удвоить все числа в строке: 10+12=22"; s = Regex.Replace(s, @"\d+", m => (int.Parse(m.Value) * 2).ToString()); Console.WriteLine(s);
var s = "Изменить формат даты: 3/18/2019"; s = Regex.Replace(s, @"(\d{1,2})/(\d{1,2})/(\d{1,4})", @"$2.$1.$3" ); Console.WriteLine(s);