Что можно делать, используя регулярные выражения
Регулярные выражения предоставляют массу возможностей, некоторые из них:
- заменять в строке все одинаковые слова другим словом, или удалять такие слова;
- выделять из строки необходимую часть. Например, из любой ссылки (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 };