Опубликован: 18.06.2007 | Доступ: свободный | Студентов: 1420 / 43 | Оценка: 4.14 / 3.29 | Длительность: 12:44:00
ISBN: 978-5-94774-604-4
Лекция 2:

Механизм работы регулярных выражений. Поиск с возвратами

< Лекция 1 || Лекция 2: 1234 || Лекция 3 >

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

#!/usr/bin/perl -w
use strict;
use re 'eval';

$_='abcd';
m!(?{ print "Starting from ".pos($_)."\n" })
  (\w
    (?{ print pos($_)."\n$1\n" })
  )*!x;

Если убрать код Perl, то оператор поиска будет выглядеть так:

m!(\w)*!x;

На печать выведется следующее:

Starting from 0
1
Use of uninitialized value in concatenation (.) or string at (re_eval 2) line 1.

2
a
3
b
4
c

Конструкция

(?{ код Perl })

вставляет код Perl в шаблон. Иногда при вставке кода в регулярное выражение транслятор выдает ошибку

Eval-group not allowed at runtime, use re 'eval' in regex m/…

Чтобы избежать этой ошибки, нужно директивой

use re 'eval';

разрешить вставку кода Perl внутрь шаблонов.

Этот код у нас распечатывает текущую позицию поиска pos в строке $_ (позиция отсчитывается от нуля) и значение переменной $1.

Вначале мы видим строку

Starting from 0

Она говорит о старте очередной итерации поиска. Эта итерация в нашем примере единственная. Далее происходит сопоставление \w и символа a, а затем - печать текущей позиции поиска (2) и значения переменной $1. Но т.к. эта печать происходит еще до закрытия захватывающей скобки, когда переменная $1 еще не появилась, то возникает предупреждающее сообщение об использовании неопределенной переменной. Конечно, его можно было бы избежать, если написать

print "$1\n" if defined $1;

Но я не стал излишне загромождать код.

Затем скобки захватывают символ a, и переменная $1 приобретает значение $1='a', а квантификатор * заставляет вернуться за закрывающую скобку и повторить поиск, начиная от \w. Теперь \w соответствует символу b, а распечатывается текущая позиция 2 и текущее значение $1, которое равно a. Затем повторяется тот же самый цикл, который печатает очередные текущие позиции и захваченные символы. После того, как подшаблон \w совпадает с d, печатается последняя позиция этой строки 4 и текущее значение $1, которое равно c. Значение d не вышло на печать, т.к. печать происходит до закрытия захватывающей скобки. А если бы мы вставили печать после нее или следующим оператором за оператором поиска, то увидели бы и значение d.

С помощью такого диагностического вывода можно отследить, как выполняется поиск. Иногда вывод показывает слишком большое число итераций и/или возвратов, которые надо оптимизировать.

< Лекция 1 || Лекция 2: 1234 || Лекция 3 >
Гулзира Урбисинова
Гулзира Урбисинова
Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?