Регулярные выражения Perl и их применение


         

Примеры применения динамических регулярных выражений


Для начала приведу простой и немного искусственный пример: пусть нам надо проверить правильность строки

Далее стоит 13 нулей: 0000000000000

Причем, число нулей может быть произвольным от 1 и более, например,

Далее стоит 2 нуля: 00

Нам надо составить регулярное выражение, которое проверяет, что число соответствует количеству нарисованных нуликов. Этот шаблон может выглядеть так:

(\d+) \D+(??{"0{$1}"})$

Работает он таким образом: вначале в переменную $1 захватывается число (13, 2 и т.д.).

Затем идет пропуск всех нецифровых символов. Внутри динамического регулярного выражения конструируется подшаблон, состоящий из символа нуля и числителя, который равен содержимому переменной $1. Для фразы

Далее стоит 13 нулей: 0000000000000

Весь шаблон после подстановки результата выполнения кода Perl будет иметь вид

(\d+) \D+0{13}$

В случае строки

Далее стоит 2 нуля: 00

Это регулярное выражение примет вид

(\d+) \D+0{2}$

Даже для строки

Далее стоит 0 нулей:

будет найдено совпадение.

В документации по Perl приводится пример применения динамических регулярных выражений для того, чтобы выяснить, является ли заданная в тексте последовательность чисел последовательностью Фибоначчи. А мы в качестве более сложного примера поставим немного другую задачу: найти в $_ первую наидлиннейшую последовательность 10-ных цифр, которые стоят подряд и возрастают на 1. Например, в строке

$_='0123 1234345678910 ';

искомая наидлиннейшая последовательность такая: 3456789.

Вот сама программа:

#!/usr/bin/perl -w use strict;

my ($len,$d,$res)=(0); $_='0123 1234345678910 '; no warnings;

/((\d) (?{$d=$+}) (?> (??{ ++$d < 10 ? "$d" : "(?!)" })* ) ) (?{ # Эти символы нельзя разделять if (length $1 > $len) { $len=length $1; $res=$1; } }) # Эту скобку нельзя отделять от предыдущей скобки "}" (?!) /x; print $res if defined $res;

Вначале переменной $len присваивается 0. В комментариях указана особенность конструкций (?{ и }), в которых фигурную скобку нельзя отделять от соседнего символа даже и при свободном форматировании.

Теперь разберемся, как работает это регулярное выражение. Вначале открывается захватывающая скобка. Позже выяснится, что она захватывает очередную длиннейшую последовательность цифр, которые возрастают на единицу. Вторая пара захватывающих скобок захватывает одну цифру. Во второй строке стоит встроенный код Perl, который запоминает эту цифру в переменной $d. Далее идет динамическое регулярное выражение, к которому записан квантификатор *. Оно вставлено в атомарные скобки.

Код в этом динамическом регулярном выражении при каждой итерации, обусловленной квантификатором *, увеличивает на единицу переменную $d, и если ее значение меньше десяти, то он возвращает значение этой переменной, а если $d после инкремента принимает значение 10, которое уже не подходит для цифры, то этот код Perl возвращает уже знакомый нам подшаблон (?!), который заставляет квантификатор * сделать шаг назад и остановиться на своем предыдущем состоянии, при котором было совпадение с наибольшей цифрой. После этого совпадения для атомарных скобок управление передается за них и выполняется код Perl, который проверяет, больше ли длина переменной $1 длины переменной $len. Если больше, значит, мы нашли более длинную последовательность цифр, поэтому мы запоминаем ее в переменной $res и обновляем содержимое переменной $len, которая хранит размер найденной длиннейшей последовательности цифр. После этого кода опять стоит подшаблон (?!), который заставляет все регулярное выражение сделать повтор со следующего символа целевого текста.

Директива no warnings нужна, чтобы отменить предупреждение

matches null string many times in regex; …



Содержание  Назад  Вперед





Forekc.ru
Рефераты, дипломы, курсовые, выпускные и квалификационные работы, диссертации, учебники, учебные пособия, лекции, методические пособия и рекомендации, программы и курсы обучения, публикации из профильных изданий