В данной статье я попытаюсь как можно лучше объяснить что такое регулярные
выражения в 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»;
if($string =~ m/berry/i){
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» и т.д. 

$lines="";
open(FILE,»file.txt») or die $!;
while(<FILE>){
if(/exit/i){
last;
}else{
$lines.=$_;
}
}
close(FILE);

Данная программа открывает файл и идет по строкам (по строкам т.к. по умолчанию
переменная $/ является переносом строки, переопределяя ее — вы меняете терминатор
строки), сохраняя каждую строчку в
переменную $lines, а если в строчке встречается
слово "exit" — то выходит из цикла. Как вы уже успели заметить я пропустил букву m в начале оператора, т.к.
этот оператор используется очень часто, то можно использовать его сокращенную
форму — без первой буквы m. Также поменять смысл на противоположный можно просто сменив оператор «=~», на 
«!~», например:

$string = «Tasty Berry»;
if($string !~ /berry/i){
print «This is NOT berry string!»;
}else{
print «This is berry string !»;
}

В данном случае будет выведена строка «This is berry string !». Но если нам
немного поменять строку, таким образом:

$string = «Tasty Strawberry»;

Логически мысля, человек ищет строчку berry (с англ. ягода), но у нас в строчке
strawberry (с англ. клубника), т.е. это нам не подходит, хотя наш шаблон все
равно сработает и выведет «This is berry string !», хотя должен вывести
«This is NOT berry string!». Это получается потому, что когда оператор получает
шаблон "berry" и другую строку, в которой он ищет, символ «b», за которым следует
«e», затем «r», «r» и «y», а все что находится до этой последовательности или после
нее, не имеет значение. Поэтому придется улучшить шаблон, подставив мнимый символ
(об этих символах ниже), вот так:

$string = «Tasty Berry»;
if($string !~ /\bberry\b/i){
print «This is NOT berry string!»;
}else{
print «This is berry string !»;
}

А вот сейчас все правильно — теперь наша программа выведет «This is NOT berry
string!". "\b" в начале шаблона это мнимый символ,
соответствующий границе слова. Как вы видите
некоторые символы имеют определенный смысл для регулярных выражений. Метасимволы
могут создавать альтернативные значения, организовывать
повторы, группировать (что позволяет запоминать часть найденной строки), создавать классы символов и
т.д. Все метасимволы начинаются с обратной косой черты (\). Если шаблон
содержи тсимволы косой черты (например анализ каталогов, или HTML тег), то лучше использовать
другие ограничители, т.к. перед каждой чертой придется ставить обратную косую черту
(\). Вот пример:

$string = «/usr/bin/perl»;
#
например вы хотите заменить каталог /bin — на /local/bin
$string =~ s/\/bin/\/local\/bin/ig;

Как видите перед каждой косой чертой пришлось ставить обратную косую черту — некрасиво и
очень громоздко, поэтому, заменим разделитель (символ ? и ‘ лучше не использовать в
качестве разделителей, т.к. шаблоны ограниченные этими символами обрабатываются иначе):

$string = «/usr/bin/perl»;
$string =~ s%/bin%/local/bin%ig;

Или можно вот так:

$string =~ s|/bin|/local/bin|ig;

Или:

$string =~ s(/bin)(/local/bin)ig;

Или так:

$string =~ s{/bin}{/local/bin}ig;

Точно также можно использовать квадратные скобки.
Эти же правила можно применять и для других операторов этого класса.
Если вы успели заметить я использовал еще один модификатор регулярных выражений, а именно
g — он означает глобальную поиск и/или замену, например:

$string = «Some path /usr/bin/perl\n…and another path /usr/bin/perl»;
$string =~ s%/bin%/local/bin%i;
print $string;

Вывод будет следующим:

Some path /usr/local/bin/perl
…and another path /usr/bin/perl

Путь изменился только в первом совпадении с шаблоном, после этого наш оператор
заканчивает работу, а вот если добавить модификатор g, тогда регулярное выражение будет
сопоставляться до конца текста, т.е. глобально. После добавления модификатора
g результат будет таков:

Some path /usr/local/bin/perl
…and another path /usr/local/bin/perl

Теперь рассмотрим все по порядку, начнем с модификаторов операторов s/…/…/ и m/…/

i — игнорирует различие между заглавными и строчными буквами
s — метасимволу точка (.) разрешено соответствовать
\n
m — разрешает метасимволам ^ и $ привязываться к промежуточным символам \n, имеющимся в тексте
x — разрешает использовать пробелы и комментарии в регулярных выражениях
g — глобальный поиск и/или замена (т.е. по всему тексту)
с — работает только для m/…/, не позволяет сбрасывать текущую позицию поиска
o — однократная компиляция шаблонов
e — говорит о том, что правый аргумент команды
s/…/…/ это исполняемый код, в
качестве подстановки будет использовано возвращаемое значение
ee — говорит о том, что правый аргумент команды
s/…/…/ это строка которую нужно выполнить как фрагмент кода, с помощью функции eval(), потом значение интерполируется

Перед тем как рассмотреть метасимволы, я хочу сказать пару слов об обычных символах.
В шаблоне любой символ соответствует самому себе если не является метасимволом или мнимым
символом, или этим символом:

"\", «|», «(«, «{«, «[«, «*», «+», «$», «?», «.»

А теперь давайте посмотрим на все метасимволы:

\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 — граница на которой остановился предыдущий глобальный поиск
(?=шаблон) — после этой точки есть фрагмент текста, который соответствует указанному регулярному выражению, 
(?!шаблон) — после этой точки нет текста, который бы соответствовал указанному
регулярному выражению, 
(?<=шаблон) — перед этой точкой есть фрагмент текста, соответствующий указанному регулярному выражению, 
(?<!шаблон) — перед этой точкой нет фрагмента текста, соответствующего указанному регулярному выражению.
(?модификаторы) — задает модификаторы, которые локальным образом меняют работу процедуры поиска. В отличие от глобальных модификаторов, имеют силу только для текущего блока, т.е. для ближайшей группы круглых скобок, охватывающих конструкцию, например, шаблон
((?i)text) соответствует слову «text» без учета регистра.
(?:шаблон) или 
(?модификаторы:шаблон) — группирует элементы шаблона. В отличие от обычных круглых скобок, не создает нумерованной переменной. Например, модификатор i не будет делать различия между строчными и заглавными буквами, однако область действия этого модификатора будет ограничена только указанным шаблоном.  
(?#текст) — комментарий, текст комментария игнорируется
(?{код}) — выполнение кода

Теперь рассмотрим квантификаторы:

+ — одно или сколько угодно совпадений
* — ноль или сколько угодно совпадений
? — ноль или одно совпадение
{n} — ровно n совпадений
{n,} — как минимум n совпадений
{n,m} — как минимум n, как максимум m совпадений

Создание групп и классов символов:

[] — класс символов
() — группа символов

Теперь несколько слов о встроенных переменных:

$’ — подстрока, следующая за совпадением. 
$& — совпадение с шаблоном поиска (при последней операции поиска или замены)
$` — подстрока, расположенная перед совпадением 
$^R — результат последнего вычисления утверждения в теле шаблона 
$n — n-ный фрагмент совпадения 
\n — n-ный фрагмент совпадения вызываемый в самом операторе (например в оп. s/…/…/)
$+ — последняя группа
$* — разрешает выполнять поиск в многострочных файлах (булевая переменная)
@- — спецмассив, который содержит начальную позицию найденного совпадения 
@+ — массив, содержащий позицию последнего найденного совпадения

(Продолжение следует)

Оставить мнение

Check Also

Алмазный фонд «Хакера». Важные материалы по взлому за последние несколько лет

В прошлом выпуске мы сделали подборку по реверсингу и анализу malware-кода, которая в перв…