Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Регулярные выражения

Читайте также:
  1. Present Simple для выражения будущего действия.
  2. Q: Оператор (statement) присваивания, который используется для присваивания результата выражения переменной имеет
  3. Английские выражения на тему «Внешность».
  4. Блоковые выражения
  5. Выполните упражнения, используя модель английских утвердительных предложений I live, слова и выражения из тестовых заданий.
  6. Выражения признательности
  7. Выражения своих мазохистских нужд. Чем большую дозу плохого обращения они

LINQ

Технология LINQ (Language Integrated Query, запрос, интегрированный в язык) представляет собой гибкий способ формирования SQL-подобных запросов, позволяющий программисту использовать стройный синтаксис для отправки запросов к любому набору данных, будь то база данных, XML-документ или обычные объекты. И, самое главное, вы можете составлять запросы в программе на хорошо знакомом вам языке С#.

Рассмотрим сначала применение технологии LINQ на примере массивов. Ниже показано, как с помощью языка интегрированных запросов можно извлечь четные числа из массива.

 

using System;

using System.Linq;

 

class Example

{

static void Main()

{

int[] myArray = {-18, 15, -4, 69, 36, 11, 98, -7, -8};

var criteria = from n in myArray

where n % 2 == 0

select n;

Console.Write("Четные значения из массива myArray: \n");

foreach (int i in criteria) Console.Write(i + " ");

Console.WriteLine();

Console.WriteLine("Нажмите любую кнопку!");

Console.ReadKey();

}

}

 

Переменная criteria является переменной запроса. Благодаря ключевому слову var переменная criteria становится неявно типизированной. Запросы начинаются с оператора from, определяющего два элемента. Первым элементом является переменная диапазона, принимающая элементы из источника данных (нашем случае это - переменная n). Вторым элементом является источник данных (в нашем случае - это массив myArray). Тип переменной диапазона выводится из источника данных. Поэтому переменная n является целочисленной.

Обобщенный синтаксис оператора from следующий:

 

from переменная диапазона in источник данных

where критерий отбора

 

Запросы оканчиваются оператором select или group.

 

Для выполнения запроса организуется следующий цикл:

 

foreach (int i in criteria) Console.Write(i + " ");

 

При разработке запросов используются следующие ключевые слова:

 

Ascending, by, descending, equals, from, group, in, into, join, let, on, orderby, select, where

 

В запросе может быть несколько операторов where. В следующем примере мы отберем элементы массива, кратные трем, но меньше 50.

 

using System;

using System.Linq;

 

class Example

{

static void Main()

{

int[] myArray = { -18, 15, -4, 69, 36, 11, 98, -7, -8, 2, 7,-6,14};

var criteria = from n in myArray

where n % 3 == 0

where n < 50

select n;

Console.Write("Числа, кратные трем, меньше 50: \n");

foreach (int i in criteria) Console.Write(i + " ");

Console.WriteLine();

Console.WriteLine("Нажмите любую кнопку!");

Console.ReadKey();

}

}

 

Результат можно упорядочить по возрастанию:

 

using System;

using System.Linq;

 

class Example

{

static void Main()

{

int[] myArray = { -18, 15, -4, 69, 36, 11, 98, -7, -8, 2, 7,-6,14};

var criteria = from n in myArray

where n % 3 == 0

where n < 50

orderby n

select n;

Console.Write("Числа, кратные трем, меньше 50, упорядоченные по возрастанию: \n");

foreach (int i in criteria) Console.Write(i + " ");

Console.WriteLine();

Console.WriteLine("Нажмите любую кнопку!");

Console.ReadKey();

}

}

 

Или по убыванию:

 

using System;

using System.Linq;

 

class Example

{

static void Main()

{

int[] myArray = { -18, 15, -4, 69, 36, 11, 98, -7, -8, 2, 7,-6,14};

var criteria = from n in myArray

where n % 3 == 0

where n < 50

orderby n descending

select n;

Console.Write("Числа, кратные трем, меньше 50, упорядоченные по убыванию: \n");

foreach (int i in criteria) Console.Write(i + " ");

Console.WriteLine();

Console.WriteLine("Нажмите любую кнопку!");

Console.ReadKey();

}

}

 

В критерии отбора допускается использование логических условий, таких как && - конъюнкция, или || - дизъюнкция.

 

using System;

using System.Linq;

class Example

{

static void Main()

{

int[] myArray = {-8,3,16,-4,71,83,2,9,32,7,-5,-3};

var criteria = from n in myArray

where n >3 && n <20

orderby n

select n;

Console.Write("Числа больше 3, но меньше 20, упорядоченные по возрастанию: \n");

foreach (int i in criteria) Console.Write(i + " ");

Console.WriteLine();

Console.WriteLine("Нажмите любую кнопку!");

Console.ReadKey();

}

}

 

Ниже рассмотрим, каким образом можно отделить русские сайты от других сайтов:

 

using System;

using System.Linq;

 

class Example

{

static void Main()

{

string[] domens =

{"www.google.com","www.cia.gov","www.un.org","www.mail.ru","www.yandex.ru",

"www.fbi.gov","www.microsoft.com","www.ibm.com"};

var netAddrs = from addr in domens

where addr.EndsWith(".ru", StringComparison.Ordinal)

select addr;

 

foreach (var str in netAddrs) Console.WriteLine(str);

Console.WriteLine("Нажмите любую кнопку!");

Console.ReadKey();

}

}

 

Теперь рассмотрим запросы к коллекции объектов. Они мало чем отличаются от запросов к массивам, но все же. В примерах ниже будем использовать следующие тестовые классы:

 

class Book

{

public string Title { get; set; }

public int Authorld { get; set; }

public int PublishYear { get; set; }

public Book(string title, int authorld, int year)

{

this.Title = title;

this.Authorld = authorld;

this.PublishYear = year;

}

 

public override string ToString()

{

return string.Format("{0} - {1}", Title, PublishYear);

}

}

 

class Author

{

public int Id { get; set; }

public string FirstName { get; set; }

public string LastName { get; set; }

public Author (int id, string firstName, string lastName)

{

this.Id = id;

this.FirstName = firstName;

this.LastName = lastName;

}

}

//...

List<Book> books = new List<Book>{

new Book("Le Rhin", 1, 1842),

new Book("Les Burgraves",1, 1843),

new Book("Napoleon le Petit",1, 1852),

new Book("Les Chatiments",1, 1853),

new Book("Les Contemplations", 1, 1856),

new Book("Les Miserables", 1, 1862) };

List<Author> authors = new List<Author>

{

new Author(1, "Victor", "Hugo")

};

 

Простейший LINQ-запрос всего лишь извлекает из коллекции информацию обо всех книгах:

 

var allBooks = from book in books select book;

foreach (Book book in allBooks)

{

Console.WriteLine(book.ToString());

}

 

Для упорядочивания результатов воспользуйтесь оператором orderby. В следующем фрагменте кода результаты упорядочиваются в порядке возрастания (по умолчанию):

 

var ordered = from book in books orderby book.Title select book;

 

Для расположения результатов в порядке убывания напишите такой код:

 

var ordered = from book in books

orderby book.Title descending

select book;

 

А вот так можно сортировать столбцы:

 

var ordered = from book in books

orderby book.PublishYear, book.Title descending

select book;

 

Можно так же, как и к массивам, применять условия фильтрации:

 

var beforel850 = from book in books

where book.PublishYear < 1850

select book;

 

Несколько условий:

 

var dateRange = from book in books

where book.PublishYear >= 1850

&& book.PublishYear <= 1855

select book;

 

С помощью LINQ можно решить такую задачу, как получение коллекции на основе отдельных полей объектов (получение проекции). Например, имея в своем распоряжении объект Book, вы хотите возвратить коллекцию объектов, содержащую только информацию о названиях книг и годах издания (опустив имя автора).

До появления LINQ для решения этой задачи требовалось написать простой, но громоздкий код для перебора всех объектов коллекции и переноса нужных свойств в новую коллекцию. Пользуясь LINQ, вы пишете одну строчку (которая разбита здесь на части исключительно из-за недостаточной ширины книжной страницы):

 

var justTitlesAfterl850 = from book in books

where book.PublishYear > 1850

select book.Title;

 

Этот запрос возвратит названия книг, изданных после 1850 года. Результат, объект justTitiesAfteri850, представляет собой коллекцию строковых объектов.

Но простые запросы на выборку данных, это еще не все, на что способно LINQ. Допустим, вы хотите объединить данные из нескольких коллекций по общему полю. Для решения такой задачи используется конструкция join. Здесь в полной мере проявляется мощь технологии LINQ. В нашем примере коллекция Author будет объединена с коллекцией Book, и в проекцию попадет только информация об авторах и о названиях книг.

 

var withAuthors = from book in books

join author in authors on book.AuthorId equals author.Id

select new { Book = book.Title,

Author = author.FirstName + " "

+ author.LastName };

Console.WriteLine("Join with authors:");

foreach (var bookAndAuthor in withAuthors)

{

Console.WriteLine("{0}, {1}",

bookAndAuthor.Book,

bookAndAuthor.Author);

}

 

Переменная withAuthors имеет анонимный тип, сгенерированный исключительно для нашего LINQ-запроса. Поскольку у этого типа нет имени (по крайней мере, в исходном коде), ключевое слово var служит для ссылки и на саму коллекцию, и на ее объекты. LINQ может сгенерировать анонимные объекты в случае необходимости, но может и присвоить соответствующие значения свойствам существующего именованного объекта, на который вы укажете.

 

Далее рассмотрим построение запросов к XML-документу. Технология LINQ включает в себя оригинальный набор классов для манипуляций с XML-кодом, оптимизированных под LINQ-запросы. Синтаксис самих запросов ничем не отличается от синтаксиса запросов к объектам. В этом примере задействован файл LesMis.xml, следующего содержания:

 

<?xml version="1.0" encoding="utf-8"?>

<Book>

<Title>Les Mis>irables</Title>

<Author>Victor Hugo</Author>

<Source Retrieved="2009-02-14T00:00:00">

<imL>http://www.gutenberg.org/files/135/135.txt</URL>

</Source>

<Chapters>

<Chapter>M. Myriel</Chapter>

<Chapter>M. Myriel becomes M. Welcome</Chapter>

<Chapter>A Hard Bishopric for a Good Bishop</Chapter>

<Chapter>Monseigneur Bienvenu made his Cassocks

last too long</Chapter>

<Chapter>Who guarded his House for him</Chapter>

<Chapter>Cravatte</Chapter>

<Chapter>Philosophy after Drinking</Chapter>

<Chapter>The Brother as depicted by the Sister</Chapter>

<Chapter>The Bishop in the Presence of an Unknown Light</Chapter>

<Chapter>A Restriction</Chapter>

<Chapter>The Solitude of Monseigneur Welcome</Chapter>

<Chapter>What he believed</Chapter>

<Chapter>What he thought</Chapter>

<Chapter>...far too many more...</Chapter>

</Chapters>

</Book>

 

Код для извлечения из него данных следующий:

 

XDocument doc = XDocument. Load ("LesMis.xml");

var chaptersWithHe = from chapter in doc.Descendants("Chapter")

where chapter.Value.Contains(" he ")

select chapter.Value;

Console.WriteLine("Chapters with xhe':");

foreach (var title in chaptersWithHe)

{

Console.WriteLine(title);

}

 

Кроме выборки данных из XML LINQ дает возможность быстро создать XML-документ, имеющий иерархическую структуру:

 

XElement xml = new XElement("Books",

new XElement("Book",

new XAttribute("year",1856),

new XElement("Title", "Les Contemplations")),

new XElement("Book",

new XAttribute("year", 1843),

new XElement("Title", "Les Burgraves"))

);

 

В результате работы этого кода будет сгенерирован следующий фрагмент XML-документа:

 

<Books>

<Book year="1856">

<Title>Les Contemplations</Title>

</Book>

<Book year="1843"> <Title>Les Burgraves</Title> </Book> </Books>

Регулярные выражения

 

Регулярные выражения (англ. regular expressions, сокр. RegExp, RegEx, жарг. регэкспы или регексы) — это формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов (символов-джокеров, англ. wildcard characters). По сути это строка-образец (англ. pattern, по-русски её часто называют «шаблоном», «маской»), состоящая из символов и метасимволов и задающая правило поиска.

Регулярные выражения произвели прорыв в электронной обработке текстов в конце XX века. Набор утилит (включая редактор sed и фильтр grep), поставляемых в дистрибутивах UNIX, одним из первых способствовал популяризации регулярных выражений для обработки текстов. Многие современные языки программирования имеют встроенную поддержку регулярных выражений. Среди них ActionScript, Perl, Java, PHP, JavaScript, языки платформы.NET Framework, Python, Tcl, Ruby, Lua, Gambas и др.

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

· найти все последовательности символов «кот» в любом контексте, как то: «кот», «котлета», «терракотовый»;

· найти отдельно стоящее слово «кот» и заменить его на «кошка»;

· найти слово «кот», которому предшествует слово «персидский» или «чеширский»;

· убрать из текста все предложения, в которых упоминается слово кот или кошка.

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

Синтаксис

Большинство символов в регулярном выражении представляют сами себя за исключением специальных символов [ ] \ / ^ $. |? * + () { }, которые могут быть предварены символом \ (обратная косая черта) («экранированы», «защищены») для представления их самих в качестве символов текста. Можно экранировать целую последовательность символов, заключив её между \Q и \E.

 

Пример Соответствие
a\.? a. или a
a\\\\b a\\b
a\[F\] a[F]
\Q+-*/\E +-*/

 

 

Аналогично могут быть представлены другие специальные символы (набор символов, требующих экранирования, может отличаться в зависимости от конкретной реализации). Часть символов, которые в той или иной реализации не требуют экранирования (например, угловые скобки < >), могут быть экранированы из соображений удобочитаемости.

 

Представление обычных символов по коду

Представление Пояснение Кодировка
\0n n — восьмеричное число от 0 до 377 8-битная
\xdd d — шестнадцатеричная цифра 16-битная (Юникод)
\udddd

Управляющие символы

Представление Символ Обозначение Расшифровка
\t Табуляция HT Horizontal tabulation
\v Вертикальная табуляция VT Vertical tabulation
\r Возврат каретки CR Carriage return
\n Перевод строки LF Line feed
\f Конец страницы FF Form feed
\a Звонок BEL Bell character
\e Escape-символ ESC Escape character
\b Забой Должен находиться внутри квадратных скобок (иначе интерпретируется как граница слова). BS Backspace
\cA … \cZ Ctrl+A … Ctrl+Z Например, последовательность \cM\cJ соответствует управляющим символам CR LF. Эквивалентно \x01 … \x1A.

 

 

Любой символ

 

Метасимвол. (точка) означает один любой символ, но в некоторых реализациях исключая символ новой строки.

 

Представление символьных классов(наборов символов)

 

Представление Эквивалент Значение
\d [0-9] Цифра
\D [^\d] Любой символ, кроме цифры
\w [A-Za-zА-Яа-я0-9_] Символы, образующие «слово» (буквы, цифры и символ подчёркивания)
\W [^\w] Символы, не образующие «слово»
\s [ \t\v\r\n\f] Пробельный символ
\S [^\s] Непробельный символ

 

Набор символов в квадратных скобках [ ] именуется символьным классом и позволяет указать интерпретатору регулярных выражений, что на данном месте в строке может стоять один из перечисленных символов. В частности, [абв] задаёт возможность появления в тексте одного из трёх указанных символов, а [1234567890] задаёт соответствие одной из цифр. Возможно указание диапазонов символов: например, [А-Яа-я] соответствует всем буквам русского алфавита, за исключением букв «Ё» и «ё».

Если требуется указать символы, которые не входят в указанный набор, то используют символ ^ внутри квадратных скобок, например [^0-9] означает любой символ, кроме цифр.

Добавление в набор специальных символов путём экранирования — самый бесхитростный способ. Однако в современных регулярных выражениях унаследован также и традиционный подход.

 

Позиция внутри строки

 

Следующие символы позволяют спозиционировать регулярное выражение относительно элементов текста: начала и конца строки, границ слова.

Представление Позиция Пример Соответствие
^ Начало строки ^a a aa aaa
$ Конец строки a$ aaa aa a
\b Граница слова a\b aa a aa a
\ba a aa a aa
\B Не граница слова \Ba\B a a a a a a
\G Предыдущий успешный поиск \Ga aaa aaa (поиск остановился на 4-й позиции — там, где не нашлось a)

 

Квантификация (поиск последовательностей)

 

Квантификатор после символа, символьного класса или группы определяет, сколько раз предшествующее выражение может встречаться. Следует учитывать, что квантификатор может относиться более чем к одному символу в регулярном выражении, только если это символьный класс или группа.

 

Представление Число повторений Пример Соответствие  
{n} Ровно n раз colou{3}r colouuur  
{m,n} От m до n включительно colou{2,4}r colouur, colouuur, colouuuur  
{m,} Не менее m colou{2,}r colouur, colouuur, colouuuur и т. д.  
{,n} Не более n colou{,3}r color, colour, colouur, colouuur  

 

Представление Число повторений Эквивалент Пример Соответствие
* Ноль или более {0,} colou*r color, colour и т. д.
+ Одно или более {1,} colou+r colour, colouur и т. д. (но не color)
? Ноль или одно {0,1} colou?r color, colour

 

Часто используется последовательность.* для обозначения любого количества любых символов между двумя частями регулярного выражения.

Символьные классы в сочетании с квантификаторами позволяют устанавливать соответствия с реальными текстами. Например, столбцами цифр, телефонами, почтовыми адресами, элементами HTML-разметки и др.

 

Если символы { } не образуют квантификатор, их специальное значение игнорируется.

 

Обозначение группы

 

Круглые скобки используются для определения области действия и приоритета операций. Шаблон внутри группы обрабатывается как единое целое и может быть квантифицирован. Например, выражение (тр[ау]м-?)* найдёт последовательность вида трам-трам-трумтрам-трум-трамтрум.

 

Обратная связь

 

Одно из применений группировки — повторное использование ранее найденных групп символов (подстрок, блоков, отмеченных подвыражений). При обработке выражения подстрОки, найденные по шаблону внутри группы, сохраняются в отдельной области памяти и получают номер начиная с единицы. Каждой подстроке соответствует пара скобок в регулярном выражении. Квантификация группы не влияет на сохранённый результат, то есть сохраняется лишь первое вхождение. Обычно поддерживается до 9 нумерованных подстрок с номерами от 1 до 9, но некоторые интерпретаторы позволяют работать с бОльшим количеством. Впоследствии в пределах данного регулярного выражения можно использовать обозначения от \1 до \9 для проверки на совпадение с ранее найденной подстрокой.

Например, регулярное выражение (та|ту)-\1 найдёт строку та-та или ту-ту, но пропустит строку та-ту.

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

Группировка без обратной связи

 

Если группа используется только для группировки и её результат в дальнейшем не потребуется, то можно использовать группировку вида (?:шаблон). Под результат такой группировки не выделяется отдельная область памяти и, соответственно, ей не назначается номер. Это положительно влияет на скорость выполнения выражения, но понижает удобочитаемость.

 

Атомарная группировка

 

Атомарная группировка вида (?>шаблон), так же как группировка без обратной связи, не создаёт обратных связей. В отличие от неё, такая группировка запрещает возвращаться назад по строке, если часть шаблона уже найдена.

 

Пример Соответствие Создаваемые группы  
a(bc|b|x)cc   abcc axcc abcc axcc a b ccaxcc abcca x cc
a(?:bc|b|x)cc нет
a(?>bc|b|x)cc abcc axcc но не abcc axcc: вариант x найден, остальные проигнорированы
a(?>x*)xa не найдётся axxxa: все x заняты, и нет возврата внутрь группы

 

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

 

Модификаторы

 

Модификаторы действуют с момента вхождения и до конца регулярного выражения или противоположного модификатора. Некоторые интерпретаторы могут применить модификатор ко всему выражению, а не с момента его вхождения.

 

Синтаксис Описание
(?i) Включает нечувствительность выражения к регистру символов (англ. case insensitivity)  
(?-i) Выключает
(?s) Включает режим соответствия точки символам переноса строки и возврата каретки
(?-s) Выключает
(?m) Символы ^ и $ вызывают соответствие только после и до символов новой строки
(?-m) с началом и концом строки
(?x) Включает режим без учёта пробелов между частями регулярного выражения и позволяет использовать # для комментариев
(?-x) Выключает

 

Группы-модификаторы можно объединять в одну группу: (?i-sm). Такая группа включает режим i и выключает режим s, m. Если использование модификаторов требуется только в пределах группы, то нужный шаблон указывается внутри группы после модификаторов и двоеточия. Например, (?-i)(?i:tv)set найдёт TVset, но не TVSET.

 

Комментарии

 

Для добавления комментариев в регулярное выражение можно использовать группы-комментарии вида (?#комментарий). Такая группа интерпретатором полностью игнорируется и не проверяется на вхождение в текст. Например, выражение А(?#тут комментарий)Б соответствует строке АБ.

 

Перечисление

 

Вертикальная черта разделяет допустимые варианты. Например, gray|grey соответствует gray или grey. Следует помнить, что перебор вариантов выполняется слева направо, как они указаны.

Если требуется указать перечень вариантов внутри более сложного регулярного выражения, то его нужно заключить в группу. Например, gray|grey или gr(a|e)y описывают строку gray или grey. В случае с односимвольными альтернативами предпочтителен вариант gr[ae]y, так как сравнение с символьным классом выполняется проще, чем обработка группы с проверкой на все её возможные модификаторы и генерацией обратной связи.

 

Просмотр вперёд и назад

 

В большинстве реализаций регулярных выражений есть способ производить поиск фрагмента текста, «просматривая» (но не включая в найденное) окружающий текст, который расположен до или после искомого фрагмента текста. Например, таким способом легко найти имя тега HTML, не включая в результат поиска окружающие его угловые скобки или другие знаки, но и не упуская их «из внимания» при поиске нужного контекста. Просмотр с отрицанием используется реже и «следит» за тем, чтобы указанные соответствия, напротив, не встречались до или после искомого текстового фрагмента.

 

Представление Вид просмотра Пример Соответствие
(?=шаблон) Позитивный просмотр вперёд Людовик(?=XVI) ЛюдовикXV, Людовик XVI, Людовик XVIII, ЛюдовикLXVII, ЛюдовикXXL
(?!шаблон) Негативный просмотр вперёд (с отрицанием) Людовик(?!XVI) Людовик XV, ЛюдовикXVI, ЛюдовикXVIII, Людовик LXVII, Людовик XXL
(?<=шаблон) Позитивный просмотр назад (?<=Сергей)Иванов Сергей Иванов, Игорь Иванов
(?<!шаблон) Негативный просмотр назад (с отрицанием) (?<!Сергей)Иванов Сергей Иванов, Игорь Иванов

 

Поиск по условию

 

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

 

Представление Пояснение Пример Соответствие
(?(?=если)то|иначе) Если операция просмотра успешна, то далее выполняется часть то, иначе выполняется часть иначе. В выражении может использоваться любая из четырёх операций просмотра. Следует учитывать, что операция просмотра нулевой ширины, поэтому части то в случае позитивного или иначе в случае негативного просмотра должны включать в себя описание шаблона из операции просмотра. (?(?<=а)м|п) ма м, п ап
(?(n)то|иначе) Если n-я группа вернула значение, то поиск по условию выполняется по шаблону то, иначе по шаблону иначе. (а)?(?(1)м|п) м ам, п а п

 

Регулярные выражения в С#. Поиск в тексте

 

Классы регулярных выражений.NET находятся в пространстве имен System.Text.RegularExpressions. В самом общем виде текстовый поиск может быть реализован так:

 

string source = "We few, we happy few, we band of brothers...";

Regex regex = new Regex("we");

MatchCollection coll = regex.Matches(source);

foreach (Match match in coll)

{

Console.WriteLine("\t\"{0}\" at position {1}",

match.Value.Trim(), match.Index);

}

 

Этот код выводит:

 

"we" at position 8

"we" at position 22

 

Рассмотрим более интересный пример. Найти все слова длиной 7 символов и более:

 

Regex regex = new Regex("[a-zA-Z]{7,}");

 

Здесь будет такой вывод:

 

"brothers" at position 3 3

 

Извлечение фрагментов текста

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

 

1234 Cherry Lane, Smalltown, USA

1235 Apple Tree Drive, Smalltown, USA

3456 Cherry Orchard Street, Smalltown, USA

 

Извлечем из текста все названия улиц:

 

string file =

"1234 Cherry Lane, Smalltown, USA" + Environment.NewLine +

"1235 Apple Tree Drive, Smalltown, USA" +

Environment. NewLine +

"3456 Cherry Orchard Street, Smalltown, USA" +

Environment. NewLine;

Regex regex = new Regex("^(?<HouseNumber>\\d+)\\s*(?<Street>

[\\w\\s]*), (?<City>[\\w]+),

(?<Country>[\\w\\s]+)$", RegexOptions.Multiline);

MatchCollection coll = regex.Matches(file);

foreach (Match m in coll)

{

string street = m.Groups["Street"].Value;

Console.WriteLine("Street: {0}", street);

}

 

Этот код выводит следующий результат:

 

Street: Cherry Lane

Street: Apple Tree Drive

Street: Cherry Orchard Street

 

Замена фрагмента текста

 

Вы можете выполнить прямую замену текста с использованием регулярных выражений. Например, требуется заменить слово после "we" на "something".

 

Regex regex = new Regex("[wW]e\\s[a-zA-Z]+");

string result = regex.Replace(source, "we something");

 

Впрочем, имеется и более мощная конструкция. Класс MatchEvaiuator позволяет выполнять сложные замены с учетом значения найденного соответствия. Рассмотрим пример, в котором слово "we" меняется местами со словом, которое за ним следует.

 

static string SwapOrder(Match m)

{

// Поменять местами " we" и слово, которое за ним следует

return m.Groups[ "OtherWord" ].Value + " we";

}

string source = "We few, we happy few, we band of brothers...";

// Поместить слово, идущее после "we", в отдельную группу,

// чтобы его можно было извлечь позже

regex = new Regex("[wW]e\\s(?<OtherWord>[a-zA-Z]+)");

// Передать наш метод классу MatchEvaluator

result = regex.Replace(source, new MatchEvaluator (SwapOrder));

Console.WriteLine("result: {0}", result);

 

Результат работы выглядит так:

 

result: few.we, happy we few, band we of brothers

 

Проверка допустимости

 

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

Regex regex = new Regex (pattern);

bool isMatch = regex.IsMatch(userString);

Console.WriteLine("{0}? {I}", userString, isMatch?"ok":"bad");

 


Дата добавления: 2015-10-29; просмотров: 139 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
выполнение кода| Программа rpm.

mybiblioteka.su - 2015-2024 год. (0.078 сек.)