Что можно делать, используя регулярные выражения

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

- заменять в строке все одинаковые слова другим словом, или удалять такие слова;
- выделять из строки необходимую часть. Например, из любой ссылки (http://mycsharp.ru/post/33/2013_10_19_virtualnye_metody_v_si-sharp_pereopredelenie_metodov.html) выделять только доменную часть (mycsharp.ru);
- проверять соответствует ли строка заданному шаблону. Например, проверять, правильно ли введен email, телефон т.д.;
- проверять, содержит ли строка заданную подстроку;
- извлекать из строки все вхождения подстрок, соответствующие шаблону регулярного выражения. Например, получить все даты из строки.

Начало работы с регулярными выражениями

Для того, чтобы работать с регулярными выражениями необходимо подключить в начале программы пространство имен using System.Text.RegularExpressions;В Си-шарп работу с регулярными выражениями предоставляет класс Regex. Создание регулярного выражения имеет следующий вид:

Regex myReg = new Regex([шаблон]);

Здесь [шаблон] – это строка содержащая символы и спецсимволы.
У Regex также есть и второй конструктор, который принимает дополнительный параметр – опции поиска. Это мы рассмотрим далее.

Приведу простой пример программы с использованием регулярных выражений:

static void Main(string[] args)
{
string data1 = "Петр, Андрей, Николай";
string data2 = "Петр, Андрей, Александр";
Regex myReg = new Regex("Николай"); // создание регулярного выражения
Console.WriteLine(myReg.IsMatch(data1)); // True
Console.WriteLine(myReg.IsMatch(data2)); // False
Console.ReadKey();
}

Здесь в качестве шаблона выступает однозначная строка "Николай". Дальше был использован метод IsMatch, который проверят, содержит ли заданная строка (data1, data2) подстроку соответствующую шаблону.

Методы класса Regex

Рассмотрим кратко методы для работы с регулярными выражениями:

IsMatch – проверяет содержит ли строка хотя бы одну подстроку соответствующую шаблону регулярного выражения. Работа этого метода показана в примере выше.

Match – возвращает первую подстроку, соответствующую шаблону, в виде объекта класса Match. Класс Match предоставляет различную информацию о подстроке – длину, индекс, само значение и другое.

static void Main(string[] args)
{
string data1 = "Петр, Андрей, Николай";
Regex myReg = new Regex("Николай");
Match match = myReg.Match(data1);
Console.WriteLine(match.Value); // "Николай"
Console.WriteLine(match.Index); // 14
Console.ReadKey();
}

Matches – возвращает все подстроки соответствующие шаблону в виде коллекции типа MatchCollection. Каждый элемент этой коллекции типа Match.

static void Main(string[] args)
{
string data1 = "Петр, Николай, Андрей, Николай";
Regex myReg = new Regex("Николай");
MatchCollection matches = myReg.Matches(data1);
Console.WriteLine(matches.Count); // 2
foreach (Match m in matches)
Console.WriteLine(m.Value); //вывод всех подстрок "Николай"
Console.ReadKey();
}

Replace – возвращает строку, в которой заменены все подстроки, соответствующие шаблону, новой строкой:

static void Main(string[] args)
{
string data1 = "Петр, Николай, Андрей, Николай";
Regex myReg = new Regex("Николай");
data1 = myReg.Replace(data1, "Максим");
Console.WriteLine(data1); //"Петр, Максим, Андрей, Максим"
Console.ReadKey();
}

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

static void Main(string[] args)
{
string data1 = "Петр,Николай,Андрей,Николай";
Regex myReg = new Regex(",");
string[] names = myReg.Split(data1); // массив имен
Console.ReadKey();
}

Специальные символы

В примерах выше рассматривались очень простые, однозначные регулярные выражения без использования спецсимволов. Спецсимволов существует достаточно много, их описание приведу ниже в таблицах:

Классы символов

Обозначение Описание Шаблон Соответствие
[группа_символов] Любой из перечисленных в скобках символов. Используя тире можно указать диапазон символов, например, [a-f] - то же самое, что [abcdef] [abc] «a» в «and»
[^группа_символов] Любой символ, кроме перечисленных в скобках [^abc] «n», «d» в «and»
\d Цифра. Эквивалентно [0-9] \d «1» в «data1»
\D Любой символ, кроме цифр. Эквивалентно [^0-9] \D «y» в «2014y»
\w Цифра, буква (латинский алфавит) или знак подчеркивания. Эквивалентно [0-9a-zA-Z_] \w «1», «5», «с» в «1.5с»
\W Любой символ, кроме цифр, букв (латинский алфавит) и знака подчеркивания. Эквивалентно [^0-9a-zA-Z_] \W «.» в «1.5с»
\s Пробельный символ (пробел, табуляция, перевод строки и т. п.) \s « » в «c sharp»
\S Любой символ, кроме пробельных \S «c» «s» «h» «a» «r» «p» в «c sharp»
. Любой символ, кроме перевода строки. Для поиска любого символа, включая перевод строки, можно использовать конструкцию [\s\S] c.harp «csharp» в «mycsharp»


Символы повторения



Обозначение Описание Шаблон Соответствие
* Соответствует предыдущему элементу ноль или более раз \d*. «a», «1b», «23c » в «a1b23c»
+ Соответствует предыдущему элементу один или более раз \d+. «1b», «23c » в «a1b23c»
? Соответствует предыдущему элементу ноль или один раз \d?\D «a», «1b», «3с» в «a1b23c»
{n} Соответствует предыдущему элементу, который повторяется ровно n раз \d{2} «43», «54», «82» в «2,43,546,82»
{n,} Соответствует предыдущему элементу, который повторяется минимум n раз \d{2,} «43», «546», «82» в «2,43,546,82»
{n,m} Соответствует предыдущему элементу, который повторяется минимум n раз и максимум m \d{2,} «43», «546», «821» в «2,43,546,8212»


Символы привязки

Обозначение Описание Шаблон Соответствие
^ Соответствие должно находиться в начале строки ^\d{2} «32» в «32,43,54»
$ Соответствие должно находиться в конце строки или до символа \n при многострочном поиске \d{2}$ «54» в «32,43,54»
\b Соответствие должно находиться на границе алфавитно-цифрового символа (\w) и не алфавитно-цифрового (\W) \b\d{2} «32», «54» в «32 a43 54»
\B Соответствие не должно находиться на границе \B\d{2} «43» в «32 a43 54»
\G Соответствие должно находиться на позиции конца предыдущего соответствия \G\d «3», «2», «4» в «324.758»


Символы выбора

Обозначение Описание Шаблон Соответствие
| Работает как логическое «ИЛИ» - соответствует первому и/или второму шаблону one|two «one», «two» в «one two three»
(группа_символов) Группирует набор символов в единое целое для которого дальше могут использоваться + * ? и т.д. Каждой такой группе назначается порядковый номер слева направо начиная с 1. По этому номеру можно ссылаться на группу \номер_группы (one)\1 «oneone» в «oneone onetwoone»
(?:группа_символов) Та же группировка только без назначения номера группы (?:one){2} «oneone» в «oneone onetwoone»


Другие символы

Обозначение Описание Шаблон Соответствие
\t Символ табуляции \t  
\v Символ вертикальной табуляции \v  
\r Символ возврата каретки \r  
\n Символ перевода строки \n  
\f Символ перевода страницы \f  
\ Символ, который позволяет экранировать специальные символы, чтобы те воспринимались буквально. Например, чтобы было соответствие символу звёздочки, шаблон будет выглядеть так \* \d\.\d «1.1», «1.2» в «1.1 1.2»


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

Приведу пример программы, которая проверят корректность электронного адреса (шаблон тот же, что и на странице регистрации на этом сайте):

static void Main(string[] args)
{
Regex myReg = new Regex(@"[A-Za-z]+[\.A-Za-z0-9_-]*[A-Za-z0-9]+@[A-Za-z]+\.[A-Za-z]+");
Console.WriteLine(myReg.IsMatch("[email protected]")); // True
Console.WriteLine(myReg.IsMatch("email@email")); // False
Console.WriteLine(myReg.IsMatch("@email.com")); // False
Console.ReadKey();
}

Здесь перед началом строки регулярного выражения стоит символ «@» который указывает комплятору воспринимать все символы буквально. Это необходимо, чтобы корректно воспринимался символ «\».

Параметры поиска

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

IgnoreCase – игнорирование регистра при поиске. Находит соответствия независимо прописными или строчными буквами в строке написано слово;
RightToLeft – поиск будет выполнен справа налево, а не слева направо;
Multiline – многострочный режим поиска. Меняет работу спецсимволов «^» и «$» так, что они соответствуют началу и концу каждой строки, а не только началу и концу целой строки;
Singleline – однострочный режим поиска;
CultureInvariant - игнорирование национальных установок строки;
ExplicitCapture – обеспечивается поиск только буквальных соответствий;
Compiled – регулярное выражение компилируется в сборку, что делает более быстрым его исполнение но увеличивает время запуска;
IgnorePatternWhitespace – игнорирует в шаблоне все неэкранированные пробелы. С этим параметром шаблон «a b» будет аналогичным шаблону «ab»;
None – использовать поиск по умолчанию.

Пример программы с использованием параметра поиска (игнорирование регистра):

static void Main(string[] args)
{
string data = "nikolay, sergey, oleg";
Regex myRegIgnoreCase = new Regex(@"Sergey", RegexOptions.IgnoreCase);
Regex myReg = new Regex(@"Sergey");
Console.WriteLine(myRegIgnoreCase.IsMatch(data)); // True
Console.WriteLine(myReg.IsMatch(data)); // False
Console.ReadKey();
}

Если необходимо установить несколько параметров, тогда они разделяются оператором поразрядного «ИЛИ» - «|»

Regex myReg = new Regex(@"Sergey", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

Приведу еще один пример использования регулярных выражений. Создадим метод, который будет принимать ссылку, а возвращать только доменное имя:

public static string GetDomain(string url)
{
Regex re = new Regex("http://", RegexOptions.IgnoreCase);
url = re.Replace(url, ""); // удаляем часть http://

Regex reWww = new Regex(@"www\.", RegexOptions.IgnoreCase);
url = reWww.Replace(url, ""); //удаляем часть www.

int end = url.IndexOf("/");
if (end != -1)
url = url.Substring(0, end);
return url;
}
static void Main(string[] args)
{
string url1 = "http://mycsharp.ru/post/33/2013_10_19_virtualnye_metody_v_si-sharp_pereopredelenie_metodov.html";
string url2 = "http://www.mycsharp.ru/post/33/2013_10_19_virtualnye_metody_v_si-sharp_pereopredelenie_metodov.html";
Console.WriteLine(GetDomain(url1)); // mycsharp.ru
Console.WriteLine(GetDomain(url2)); // mycsharp.ru
Console.ReadKey();
}

Домашнее задание

1. Создайте программу, которая будет проверять корректность ввода логина. Корректным логином будет строка от 2-х до 10-ти символов, содержащая только буквы и цифры, и при этом цифра не может быть первой.

2. Создайте фильтр мата. Метод будет принимать исходную строку, и возвращать результат, где нехорошие слова будут заменены на «цензура». Обработайте хотя бы одно такое слово, только предусмотрите множество его форм. Если вы собираетесь результат вашей работы оставить здесь, в комментариях, тогда фильтруйте любые другие слова, но не маты :)

PS. Не забудьте поделиться с друзьями этой статьей с помощью кнопок социальных сетей.

Перечисления (enum) в Си-шарп Перечисление (Enumeration) – это определяемый пользователем целочисленный тип, который позволяет специфицировать набор допустимых значений, и назначить каждому понятное имя.

Для объявления перечисления используется ключевое слово enum. Общая структура объявления перечисления выглядит так:

enum [имя_перечисления] { [имя1], [имя2], … };

Например, создадим перечисление Directions, которое будет соответствовать направлениям движения:

enum Directions { Left, Right, Forward, Back };

Объявив таким образом перечисление, каждой символически обозначаемой константе присваивается целочисленное значение, начиная с 0 (Left = 0, Right = 1 …). Это целочисленное значение можно задавать и самому:

enum Directions { Left, Right = 5, Forward = 10, Back };

Back в этом примере будет иметь значение 11.

Пример программы с использованием перечисления:

enum Directions { Left, Right, Forward, Back }; // объявление перечисления

class Program
{
public static void GoTo(Directions direction)
{
switch (direction)
{
case Directions.Back:
Console.WriteLine("Go back");
break;
case Directions.Forward:
Console.WriteLine("Go forward");
break;
case Directions.Left:
Console.WriteLine("Turn left");
break;
case Directions.Right:
Console.WriteLine("Turn right ");
break;
}
}

static void Main(string[] args)
{
Directions direction = Directions.Forward;
GoTo(direction); // "Go forward"
Console.ReadKey();
}
}

Чтобы получить целое значение определенного элемента перечисления, достаточно этот элемент явно привести к целому типу:

enum Directions : byte { Left, Right, Forward, Back };

class Program
{
static void Main(string[] args)
{
Console.WriteLine((int)Directions.Forward); // 2
Console.ReadKey();
}
}

По умолчанию в качестве целого типа для enum используется int. Этот тип можно изменить на любой другой целый тип (кроме char), указав после имени перечисления необходимый тип и разделив двоеточием:

enum Directions : byte { Left, Right, Forward, Back };

Наши рекомендации