русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


З регулярними виразами


Дата додавання: 2015-01-08; переглядів: 1089.


 

Класи бібліотеки .NET для роботи з регулярними виразами об'єднані в простір імен System.Text.RegularExpressions.

Почнемо з класу Regex, що представляє власне регулярний вираз. Клас є незмінним, тобто після створення екземпляра, його коректування не допускається. Для опису регулярного виразу в класі визначено декілька перевантажених конструкторів:

Regex () - створює порожній вираз;

Regex(String) - створює заданий вираз;

Regex(String, Regexoptions) - створює заданий вираз і задає параметри для його обробки за допомогою елементів перелічення RegexOptions (наприклад, розрізняти або не розрізняти прописні і рядкові букви).

Приклад конструктора, задаючого вираз для пошуку в тексті слів, що повторюються, розташованих підряд і розділених довільною кількістю пропусків, незалежно від регістра:

 

Regex гх = new Regex( @"\b(?<word>\w+)\s+(\k<word>)\b",

RegexOptions.IgnoreCase );

 

Пошук фрагментів рядка, відповідних заданому виразу, виконується за допомогою методів IsMatch, Match і Matches.

Метод IsMatch повертає true, якщо фрагмент, відповідний виразу, в заданому рядку знайдений, і false в іншому випадку. У лістингу 14.3 приведений приклад пошуку слів, що повторюються, в двох тестових рядках. У регулярний вираз, приведений раніше, доданий фрагмент, що дозволяє розпізнавати розділові знаки.

 

Лістинг 14.3. Пошук в рядку дубльованих слів (методом IsMatch)

 

using System;

using System.Text.RegularExpressions;

 

namespace exam102

{

public class Test

{

static void Main(string[] args)

{

Regex r = new Regex( @"\b(?<word>\w+)[.,:;!? ]\s*(\k<word>)\b",

RegexOptions.IgnoreCase);

string tstl = "Oh. oh! Give me more!";

if ( r.IsMatch( tstl ) ) Console.WriteLine(" tstl yes" );

else Console.WriteLine( " tstl no" );

string tst2 = "Oh give me. give me more!";

if ( r.IsMatch( tst2 ) ) Console.WriteLine(" tst2 yes" );

else Console.WriteLine( " tst2 no" );

}

}

}

Результат роботи програми:

tst1 yes

tst2 no

Слова, що повторюються, в рядку tst2 розташовуються не підряд, тому вони не відповідають регулярному виразу. Для пошуку слів, що повторюються, розташованих в довільних позиціях рядка, в регулярному виразі потрібно замінити пропуск (\s) “будь-яким символом” (.) :

 

Regex r = new Regex( @"\b(?<word>\w+)[..:;!? ].*(\k<word>)\b", RegexOptions.IgnoreCase ) ;

 

Метод Match класу Regex, на відміну від методу Ismatch, не просто визначає, чи відбувся збіг, а повертає об'єкт класу Match - черговий фрагмент, що збігся із зразком. Розглянемо лістинг 14.4, в якому використовується цей метод.

Лістинг 14.4. Виділення з рядка слів і чисел (методом Match)

using System;

using System.Text.RegularExpressions;

 

public class Test

{

static void Main(string[] args)

{

string text = "Салат - $4, борщ - $3,одеколон - $10.";

string pattern = @"(\w+) - \$(\d)[.,]";

Regex r = new Regex(pattern);

Match m = r.Match(text);

int total = 0;

 

while ( m.Success)

{

Console.WriteLine( m );

total += int.Parse( m.Groups[2].ToString() );

m = m.NextMatch();

}

 

Console.WriteLine( "Разом: $" + total );

}

}

 

Результат роботи програми:

 

Салат - $4,

борщ - $3,

одеколон - $10.

Разом: $17

 

При першому зверненні до методу Match повертається перший фрагмент рядка, що збігся з регулярним виразом pattern. У класі Match визначена властивість Groups, що повертає колекцію фрагментів, що збіглися з підвиразами в круглих дужках. Нульовий елемент колекції містить весь фрагмент, перший елемент - фрагмент, що збігся з підвиразом в перших дужках, другий елемент - фрагмент, що збігся з підвиразом в других дужках, і так далі. Якщо при визначенні виразу задати фрагментам імена, як це було зроблено в попередньому лістингу, можна буде звернутися до них по цих іменах, наприклад:

 

string pattern - @"(?'name'\w+) - \$(?'price'\d + )[.,]";

total += int.Parse( m.Groups["price"].ToString() );

 

Метод NextMatch класу Match продовжує пошук в рядку з того місця, на якому закінчився попередній пошук.

Метод Matches класу Regex повертає об'єкт класу Matchcollection - колекцію всіх фрагментів заданого рядка, що збіглися із зразком.

Розглянемо тепер приклад застосування методу Split класу Regex. Цей метод розбиває заданий рядок на фрагменти відповідно до роздільників, заданих за допомогою регулярного виразу, і повертає ці фрагменти в масиві рядків. У лістингу 14.5 рядок з лістингу 14.4 розбивається на окремі слова.

 

Лістинг 14.5. Розбиття рядка на слова (методом Split)

 

using System;

using System.Text.RegularExpressions;

using System.Collections.Generic;

 

public class Test

{

static void Main(string[] args)

{

string text = "Салат - $4, борщ - $3, одеколон - $10.";

string pattern = "[- ,.]+";

Regex r = new Regex(pattern);

List<string> words = new List<string>(r.Split(text));

foreach (string word in words) Console.WriteLine(word);

 

}

}

 

Результат роботи програми:

Салат

$4

борщ

$3

одеколон

$10

 

Метод Replасе класу Regex дозволяє виконувати заміну фрагментів тексту. Визначено декілька перевантажених версій цього методу. От як виглядає приклад простого застосування методу в його статичному варіанті, замінюючого всі входження символу $ символами у. о. :

 

string text = "Салат - $4, борщ -$3, одеколон - $10.";

string textl = Regex.Replасе( text, @"\$", "y.о." );

Інші версії методу дозволяють задавати будь-які дії із заміни за допомогою делегата MatchEvaluator, який викликається для кожного входження фрагмента, що збігся із заданим регулярним виразом.

Окрім класів Regex і Match в просторі імен System.Text.RegularExpres-sions визначені допоміжні класи, наприклад, клас Capture - фрагмент, що збігся з підвиразом в круглих дужках; клас CaptureCollection - колекція фрагментів, що збіглися зі всіма підвиразами в поточній групі; клас Group містить колекцію Capture для поточного збігу з регулярним виразом і так далі.

Як реальний приклад застосування регулярних виразів розглянемо програму аналізу файлу журналу веб-сервера. Це текстовий файл, кожен рядок якого містить інформацію про одне з'єднання з сервером. Чотири рядки файлу приведено нижче:

 

ppp-48.pool-113.spbnit.ru - - [31/Мау/2002:02:08:32 +0400] "GET / НТТР/1.1" 200

2434 "http://www.price.ru/bin/price/firminfo_f?fid=10922&where=01&base=2"

"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"

81.24.130.7 - - [31/May/2002:08:13:17 +0400] "GET /swf/menu.swf HTTP/1.1” 200

4682 "-" "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)"

81.24.130.7 - - [31/May/2002:08:13:17 +0400] "GET /swf/header.swf HTTP/1.1" 200

21244 "-" "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)"

gate.solvo.ru - - [31/May/2002:10:43:03 +0400] "GET / HTTP/1.0" 200 2422

"http://www.price.ru/bin/price/firminfo_f?fid=10922&where=01&base=l"

"Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"

 

Подібні файли можуть мати дуже значний об'єм, тому складання підсумкового звіту в зручному форматі має важливе значення. Якщо розглядати кожен рядок файлу як сукупність полів, розділених пропусками, то поле номер 0 містить адресу, з якої виконувалося з'єднання з сервером, поле номер 5 - операцію (GET при завантаженні інформації), поле 8 - ознаку успішності виконання операції (200 - успішно) і, нарешті, поле 9- кількість переданих байтів.

Приведена в лістингу 14.6 програма формує у форматі HTML підсумковий звіт, що містить таблицю адрес, з яких виконувалося звернення до сервера, і сумарну кількість переданих байтів для кожної адреси.

 

Лістинг 14.6. Аналіз журналу веб-сервера

 

using System;

using System.Collections.Generic;

using System.IO;

using System.Text.RegularExpressions;

 

public class Testm

{

public static void Main(string[] args)

{

StreamReader f = new StreamReader("access.log" );

StreamWriter w = new StreamWriter("report.htm" );

Regex get = new Regex("GET" );

Regex r = new Regex(" ");

string s,entry;

int value;

string[] items = new string[40];

Dictionary<string,int> table = new Dictionary<string, int>();

while ((s = f.ReadLine()) != null)

{

items = r.Split(s);

if (get.IsMatch(items[5]) && items[8] == "200")

{

entry = items[0];

value = int.Parse(items[9]);

if (table.ContainsKey(entry)) table[entry] += value;

else table[entry] = value;

}

}

f.Close();

w.Write("<html><head><title> Report </title></head><body>" +

"<table border =1 <tr><td> Computer <td> Bytes </tr>");

foreach ( string item in table.Keys )

w.Write( "<tr><td>{0}<td>{l}</tr>", item, table[item] );

w.Write( "</table></body>" );

w.Close();

}

}

 

Фрагмент результату роботи програми показаний у вигляді таблиці 14.5

 

Таблиця 14.5

Фрагмент журналу веб-сервера

 

Computer Bytes
ppp-48 pool-113.spbnit.ru
Test223.sovam.com
210.82.124,83
ipblock209-209.octetgroup.net
81.24.130.7
gate.solvo.ru
212.113.108.164

 

Файл access.log прочитується по рядкам, кожен рядок розбивається на поля, які заносяться в масив items. Потім, якщо завантаження пройшло успішно, про що свідчать значення GET і 200 полів 5 і 8, кількість переданих байтів (поле 9) перетвориться в ціле і заноситься в хеш-таблицю по ключу, яким служить адреса, що зберігається в полі 0.

Для формування HTML-файла report.htm використовуються відповідні теги. Файл можна проглянути, наприклад, за допомогою Internet Explorer. Програма вийшла дуже компактною за рахунок використання стандартних класів бібліотеки .NET.

 


<== попередня лекція | наступна лекція ==>
Метасимволи | Документування у форматі XML


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн