Регулярні висловлювання в Delphi - Форум програмістів
-
Символи
-
Будь-який символ збігається із самим собою (якщо він не відноситься до метасимволів). Будь-яка послідовність символів збігається з такою ж у вхідному рядку. Щоб уявити метасимволи ., - [ ] та інші в регулярних висловлюваннях без інтерпретації, тобто як простих (не спеціальних) символів необхідно випередити їх зворотною косою рисою: \. Цей прийом називається захистом метасимволів. Наприклад, щоб уявити сам символ «точка» (просто точка, і нічого більше), треба написати. (Зворотна коса риса, а за нею - крапка). Сам метасимвол \ теж може бути захищений, тобто представлений як (дві зворотних косих риси), і тоді інтерпретатор регулярних виразів сприйме його як простий символ зворотної косої риси. Також можна використовувати escape-послідовності, наприклад,
Вікіпедія- вільна енциклопедія, в якійкоженможе змінити або доповнити будь-яку статтю
Цю проблему можна вирішити двома способами. Перший у тому, що у регулярному вираженні враховуються символи, які відповідають бажаному зразку ([^>]* для вищеописаного випадку). Другий полягає у визначенні квантифікатора як "нежадібного" ("ледачого", lazy), додавши після нього знак питання.
Вікіпедія- вільна енциклопедія, в якійкоженможе змінити або доповнити будь-яку статтю
"Жадібні" варіанти квантифікаторів намагаються захопити якомога більшу частину вхідного тексту, тоді як "не жадібні" - якнайменшу. Наприклад, 'b+' як і 'b*' застосовані до вхідного рядка 'abbbbc' знайдуть 'bbbb', тоді як 'b+?' знайде тільки'b', а 'b*?' - взагалі - порожній рядок; 'b?' знайде 'bb', тоді як 'b' знайде 'bbb'.Альтернативи
-
Потрібні, коли необхідно поєднати кілька правил в одне. При цьому збіг зараховується, коли є збіг хоча б із одним правилом. Бажано альтернативи укладати всередину угруповання (круглі дужки). Правила, що входять у випадок, поділяються (вертикальною рисою). Приклади:
У цьому прикладі продемонстровано альтернативу угрупованні. В принципі альтернатива може існувати і поза групуванням, але так виникає більше помилок.Угруповання
-
Використовуються, коли потрібно обробляти результат частинами. Наприклад, при обробці посилань у HTML-документі зручно окремо обробляти текст посилання та URL-адресу. Угруповання полягають у круглі дужки.
-
Модифікатори призначені зміни поведінки правила. Призначення та приклади - дивись у довідці.
-
Розглянемо кілька прикладів використання регулярних виразів у Delphi.
Приклад використання
-
Використовувати регулярні вирази в Delphi просто. Розпаковуємо архів у будь-який каталог. Додаємо RegExpr.pas (розміщений у підкаталозі Source) до списку файлів нашого проекту (головне меню Delphi Project -> Використовуємо клас TRegExpr у нашому проекті. Не забудьте додати 'uses RegExpr' у соотв. модулі проекту. Отже, невеликий приклад. Спробуємо знайти у рядку всі цілі числа. Регулярне вираз цього випадку виглядатиме так: -?d+, тобто. містити відповідний символьний клас \d (тобто цифри) та квантифікатор +, що означає будь-яку кількість. Думаю, те, що ціле число є довільною кількістю цифр зрозуміло. ;-) Також перед числом можливо буде стоятизнак мінус. Решта має бути зрозумілою з коментарів.
// Дуже простий приклад - вилучення чисел із введеного рядка. program Project1;
uses SysUtils, // додаємо потрібний модуль RegExpr in 'RegExpr.pas';
var // нам необхідний екземпляр класу TRegExpr RegExp: TRegExpr; s: string;
begin // виводимо запит і зчитуємо рядок Write('Enter a string containing numbers: '); Readln(s);
// створюємо об'єкт RegExp := TRegExpr.Create;
// гарантує звільнення зайнятої об'єктом пам'яті try // регулярне вираз перебуває у властивості Expression RegExp.Expression := '-?\d+'; // шукаємо перший збіг за допомогою функції // Exec(const AInputString : string) : boolean, яка поверне true, // якщо в рядку AInputString буде знайдено збіг з // регулярним виразом , що зберігаються у свойстві Expression if RegExp.Exec(s) then // якщо знаходимо begin Writeln('Entered string contains numbers: '); repeat // виводимо знайдений вираз, що зберігається в Match[0] Writeln(RegExp.Match[0]); // і продовжуємо пошук until not RegExp.ExecNext; end else // інакше - повідомляємо, що нічого не знайшли Writeln('Entered string contains no numbers!'); finally RegExp.Free; end; Readln; end.
// Трохи складніший приклад - вилучення цілої і дробової частини числа. // Регулярне вираз містить варіанти і подвыражения.
uses SysUtils, // додаємо потрібний модуль RegExpr in 'RegExpr.pas';
var // нам необхідний екземпляр класу TRegExpr RegExp: TRegExpr; s: string;
begin // виводимо запит і зчитуємо рядок Write('Enter a string containing numbers: '); Readln(s);
//створюємо об'єкт RegExp := TRegExpr.Create;
// гарантує звільнення зайнятої об'єктом пам'яті try // регулярне вираз перебуває у властивості Expression RegExp.Expression := '(\d+)([.,])(\d+)'; if RegExp.Exec(s) then // якщо знаходимо begin Writeln('Whole number: ', RegExp.Match[0]); Writeln('Integer part: ', RegExp.Match[1]); Writeln('Divider:', RegExp.Match[2]); Writeln('Fractional part: ', RegExp.Match[3]); end else // інакше - повідомляємо, що нічого не знайшли Writeln('Entered string doesn't contain any number!'); finally RegExp.Free; end; Readln; end.
Регулярне вираження при цьому випадку виглядатиме дещо складніше: (d+)([.,])(d+), тобто. містити соотв. подвыражения (ціла і дробова частини) і варіант (як роздільника може бути як точка, і кома), який також є подвыражение. Вираз, соотв. всьому регулярному виразу, як і раніше, знаходиться в Match[0], а ось Match[i] містить i-е угруповання. Зверніть також увагу на досить цікаву функцію
яка повертає ATemplate, у якому все '$&' і '$0' замінені на знайдене регулярне вираз, а '$n' на n-ий вираз. Наприклад, оператор
При натисканні на кнопку реалізуємо показ діалогу вибору текстового файлу та завантаження його в Memo1.
Тепер давайте реалізуємо збір статистики зі зміною тексту в Memo1:
procedure TForm1.Memo1Change(Sender: TObject); var Count, i: Integer; RegExp: TRegExpr; begin RegExp := TRegExpr.Create;
// Кількість рядків Label1.Caption := 'Рядок: ' + IntToStr(Memo1.Lines.Count);
// Кількість символів Label2.Caption := 'Символів: ' + IntToStr(Length(Memo1.Text));
// усимволів, за винятком пробільних Count := 0; RegExp.Expression := '\s'; Count := Count + Length(RegExp.Replace(Memo1.Text, '', False)); Label3.Caption := 'Непробільні символи: ' + IntToStr(Count);
// Кількість слів Count := 0; RegExp.Expression := '\s*[^\s.-]+-?[^\s.-]*'; якщо RegExp.Exec(Memo1.Text) then repeat Count := Count + 1; until not RegExp.ExecNext; Label4.Caption := 'Слов:' + IntToStr(Count);
// Кількість пропозицій Count := 0; RegExp.Expression := '[. ]+(\s$)'; for i := 0 to Memo1.Lines.Count - 1 do якщо RegExp.Exec(Memo1.Text) then repeat Count := Count + 1; until not RegExp.ExecNext; Label5.Caption := 'Пропозицій: ' + IntToStr(Count); end;
По-перше, зупинимося на підрахунку кількості символів, за винятком пробільних. Тут був використаний метод
що замінює в AInputStr всі входження регулярного виразу на AreplaceStr. Обчислюючи суму довжин отриманих в такий спосіб рядків, отримаємо шукану величину.
Тепер подивимося на підрахунок кількості пропозицій у нашому прикладі. Відповіддю на запитання «Що треба знайти?», буде, швидше за все, «Кількість точок, знаків вигуку та знаків питання, що стоять наприкінці слова чи рядка.» Крім того, слід враховувати можливість наявності непоодиноких розділових знаків (…, !?). Складаємо регулярний вираз '[. ]+(\s$)', і власне все! Завдання вирішено!
При підрахунку кількості слів можна, наприклад, використовувати регулярний вираз виду '\s*[^\s.-]+-?[^\s.-]*. Слово може йти за пробілом, а може й ні (якщо стоїть на початку тексту). Тому на початку нашого виразу стоїть \s*. Власне слово (написане без орфографічних помилок) – послідовність непробільних символів. Тобто ми могли б записати регулярне поразка так: '\s*[\S]'.Але під такий шаблон потраплять і деякі інші символи та їх послідовності, які навряд чи можна назвати словами — крапка, тире. Щоб виправити ситуацію, ми пишемо '\s*[^\s.-]'. Ну і, нарешті, необхідно врахувати наявність слів, які пишуться через дефіс та отримаємо '\s*[^\s.-]+-?[^\s.-]*. Важливо розуміти, що основна перевага при використанні регулярних виразів полягає в економії часу! Вам необхідно лише поставити запитання «Що треба знайти?» і скласти регулярний вираз, який є відповіддю на це питання, а не розробляти «з нуля» алгоритм пошуку.