Регулярні вирази та пошук тексту в Perl
Архів номерів / 2003 / Випуск №8 (9) / Регулярні вирази та пошук тексту в Perl
ВОЛОДИСЛАВ ГОРОШКО
Регулярні вирази та пошук тексту в Perl
У цій статті я спробую якнайкраще пояснити, що таке регулярні вирази в Perl. Родзинкою Perl є робота з текстом – для цього він був створений. Регулярні вирази дуже часто використовуються в Unix-системах, наприклад, для пошуку файлів за шаблоном, також у sh, прикладів багато і все не перерахувати, Perl не є винятком.
У деяких випадках синтаксис регулярних виразів може бути трохи іншим, але зрозумівши синтаксис регулярних виразів Perl, з іншими проблемами не буде.
Я читав багато статей з цього приводу і бачив багато книг, але дійсно добре описуючого матеріалу не знайшов, тому що в одних книгах занадто сильно розтягують матеріал і втрачають основну нитку оповідання, а в інших навпаки дуже мало. Тому я вирішив написати цю статтю, в якій я постараюся оптимально і ясно розповісти про регулярні вирази та пошук тексту. Причому не просто на словах, а на великій кількості прикладів.
Почнемо з того, що Perl має три основних оператори для роботи з текстом:
- m/. / - перевірка збігів (matching)
- s/. /. / - підстановка тексту (substitution)
- tr/. /. / - трансляція тексту (translation)
також парочка корисних функцій:
- substr(EXPR,OFFSET,LEN,REPLACEMENT)
- split(/PATTERN/,EXPR,LIMIT)
Оператор m/. / намагається зіставити шаблон, вказаний як аргумент, з текстом, з яким йде порівняння. Наприклад:
$string = "Tasty Berry";
print "This is berry string!";
У цьому випадку буде виведено рядок This is berry string!. Для порівняння скаляра із шаблоном потрібно використовувати порівняння такого виду «=
Тут операратор m/. / поверне істину або брехню (бо цей регулярний вираз використовується в скалярному контексті, а не в списковому – про нього нижче), якщо його опустити, то оператор m/. / буде використовувати спеціальну змінну $_.
Літера i після другої косої риси означає ігнорування регістру, як ви бачите, у шаблоні написано «berry», а $string – «Berry», тобто. якби не було літери i, то наша програма не вивела б рядок This is berry string!. Шаблон m/berry/i збігається з рядками "BERRY", "berry", "BeRrY" і т.д.
open(FILE,"file.txt") or die $!;
Дана програма відкриває файл і йде за рядками (за рядками, тому що за замовчуванням змінна $/ є перенесенням рядка, перевизначаючи його, ви змінюєте термінатор рядка), зберігаючи кожний рядок у змінну $lines, а якщо у рядку зустрічається слово «exit », то виходить із циклу.
Як ви вже встигли помітити, я пропустив літеру m на початку оператора: цей оператор використовується дуже часто і можна використовувати його скорочену форму без першої літери m.
Також змінити сенс на протилежний можна просто змінивши оператор «=
$string = "Tasty Berry";
print "This is NOT berry string!";
print "This is berry string!";
У цьому випадку буде виведено рядок This is berry string!. Але якщо нам трохи поміняти рядок таким чином:
$string = "Tasty Strawberry";
Логічно думаючи, людина шукає рядок berry (з англ. ягода), але ми в рядку strawberry (з англ. полуниця), тобто. це нам не підходить, хоча наш шаблон все одно спрацює і виведе This is berry string!, хоча повинен вивести This is NOTberry string!». Це виходить, тому що, коли оператор отримує шаблон «berry» та інший рядок, в якому він шукає символ «b», за яким слідує «e», потім «r», «r» та «y», а все, що знаходиться до цієї послідовності або після неї, не має значення. Тому доведеться покращити шаблон, підставивши уявний символ (про ці символи нижче), ось так:
$string = "Tasty Berry";
print "This is NOT berry string!";
print "This is berry string!";
А ось зараз все правильно – тепер наша програма виведе This is NOT berry string!
«» на початку шаблону – це уявний символ, який відповідає межі слова. Як ви бачите, деякі символи мають певний сенс для регулярних виразів. Метасимволи можуть створювати альтернативні значення, організовувати повтори, групувати (що дозволяє запам'ятовувати частину знайденого рядка), створювати класи символів тощо. буд. Усі метасимволи починаються із зворотної косою риси (). Якщо шаблон містить символи косої риси (наприклад, аналіз каталогів, або HTML-тег), краще використовувати інші обмежувачі, т.к. перед кожною межею доведеться ставити зворотну косу межу ().
# наприклад, ви хочете замінити каталог /bin - на /local/bin
Як бачите, перед кожною косою рисою довелося ставити зворотну косу межу - некрасиво і дуже громіздко, тому замінимо роздільник (символи ? і "краще не використовувати як роздільники, тому що шаблони, обмежені цими символами, обробляються інакше):
Або можна ось так:
Так само можна використовувати квадратні дужки. Такі ж правила можна застосовувати і для інших операторів цього класу. Якщо ви встигли помітити, я використав ще один модифікатор регулярних виразів, а саме g – він означає глобальний пошук та/або заміну, наприклад:
$string = "Якщо один файл /usr/bin/perl . and another path usr/bin/perl";
Висновок буде наступним:
Один файл /usr/local/bin/perl
. and another path /usr/bin/per
Як ви бачите, шлях змінився тільки в першому збігу з шаблоном, після цього наш оператор закінчує роботу, а якщо додати модифікатор g, тоді регулярне вираз буде зіставлятися до кінця тексту, тобто. глобально. Після додавання модифікатора g результат буде таким:
Один файл /usr/local/bin/perl
. and another path /usr/local/bin/per
Тепер розглянемо все по порядку, почнемо з модифікаторів операторів s/. /. / та m/. /:
Перед тим як розглянути метасимволи, я хочу сказати кілька слів про звичайні символи. У шаблоні будь-який символ відповідає самому собі, якщо не є метасимволом або уявним символом, або цим символом:
А тепер давайте подивимося на всі метасимволи:
- \077 - вісімковий символ;
- \xFF – шістнадцятковий символ;
- \a – символ дзвінка (alarm);
- \c[ – управляючі знаки, тобто. CTRL + , у разі це ESC;
- \f – символ прогону сторінки;
- \d - відповідає цифрі;
- \D – відповідає будь-якому символу, крім цифр;
- \e – символ ESC;
- \l – наступна літера стає малою;
- \L – всі наступні літери стають малими (аж до E);
- \u – наступна літера стає великою;
- \U - всі наступні літери стають великими (аж до E);
- \r - повернення каретки (CR);
- \n – символ нового рядка (LF);
- \t – символ горизонтальної табуляції;
- \v – символ вертикальної табуляції;
- \Q - всенаступні метасимволи стають звичайними (до E);
- \E – кінець дії команд L, U та Q;
- \s – відповідає будь-якому пробіловому символу (тобто пробіл, символ вертикальної/горизонтальної табуляції, символу нового рядка тощо);
- \S – будь-який символ, крім пробільного;
- \w – алфавітно-цифровий символ (будь-яка цифра, буква або символ підкреслення);
- \W – будь-який символ, окрім літери, цифри або символу підкреслення.
Також у Perl є певні символи, які відповідають не якійсь літері, а означають виконання якоїсь умови, вони називаються уявними символами. Ось вони:
- - альтернатива;
- ! – символ логічного NOT;
- . – будь-який символ, крім перенесення рядка;
- ^ – початок рядка тексту;
- $ – кінець рядка тексту;
- \b – межа слова;
- \B – відсутність межі слова;
- \A – «справжній» початок рядка;
- \Z – «справжній» кінець рядка або позиція перед символом початку нового рядка, розташованим у «справжньому» кінці рядка;
- \z – «справжній» кінець рядка;
- \G – кордон, де зупинився попередній глобальний пошук;
- (?=шаблон) – після цієї точки є фрагмент тексту, який відповідає зазначеному регулярному виразу;
- (?!шаблон) – після цієї точки немає тексту, який би відповідав зазначеному регулярному виразу;
- (?)
Можна замінити цим, з використанням альтернативи:
# це перебір порівняно з текстом, тобто. якщо хоча б
один фрагмент з альтернативи збігається з текстом,
то повертається значення прийме істину, тобто. в данному
#у випадку, якщо користувач введе в STDIN, exit або quit або
# же stop, то ми завершимо цикл
Потрібно перевірити, чи є у рядку слово ALPHA та слово BETA: