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

Специальные переменные, используемые в регулярных выражениях

< Лекция 10 || Лекция 11: 123 || Лекция 12 >

11.3. Имитация именованного сохранения

Регулярные выражения в 5-ой версии Perl не поддерживают именованного сохранения найденных фрагментов текста, а поддерживают только переменные с номером. Это создает неудобства, а при использовании объектов регулярных выражений, которые сохраняют найденные фрагменты текста, тяжело модифицировать эти объекты, если надо ввести новую сохраняющую переменную. В 6-й версии Perl должно появиться именованное сохранение, когда вместо номера переменной можно задать ей произвольное имя и обращаться к такой переменной по имени. А пока для этого остается использовать встроенный код и специальную переменную $^N. Например, у нас есть объект регулярного выражения, который сохраняет URL:

my $re=qr/<a\s+href="([^"]+)"/i;

Мы можем его использовать в коде

$_='<a href="http://www.intuit.ru">';
print $1 if /$re/;

И напечатается

http://www.intuit.ru

URL получается в переменной $1. Если объект регулярного выражения $re входит кирпичиком в более крупное регулярное выражение, то нумерованные переменные использовать рискованно, т.к. при вставке новых объектов или редактировании существующих нумерация может сбиться и URL может оказаться уже не в переменной $1, а в другой нумерованной переменной. Мы можем объявить переменную $url и всегда сохранять в ней найденный URL, воспользовавшись тем, что переменная $^N является копией нумерованной переменной, которая соответствует последней паре захватывающих скобок:

my $url;
my $re=qr/<a\s+href="([^"]+)(?{$url=$^N})"/i;
$_='<a href="http://www.intuit.ru">';
print $url if /$re/;

Опять напечатается

http://www.intuit.ru

Подобный кирпичик $re может войти в здание более сложного регулярного выражения, не влияя на другие переменные, сохраняющие фрагменты текста. Но встроенный код, конечно, требует дополнительного времени для выполнения.

11.4. Избавление от "вредных" специальных переменных и предварительного копирования текста

Перед применением регулярного выражения Perl, как правило, создает копию целевого текста. Это нужно, например, если после использования регулярного выражения идет обращение к нумерованным переменным. Ведь программист может изменить целевой текст, но содержимое нумерованных переменных не должно меняться, чтобы не вызвать неразбериху.

Perl не создает каждый раз при использовании регулярного выражения специальные переменные $1, $+, $` и т.д., он просто создает копию целевого текста и эти переменные ссылаются на фрагменты текста в этой копии. Это экономит время, ведь не всегда эти переменные потом будут затребованы программистом.

Целевой текст может оказаться большим, и система вынуждена будет тратить время и память на его дублирование, хотя этот дубль может и не понадобиться. Если мы не используем захватывающих скобок, будет ли Perl создавать копию целевого текста?

Будет, т.к. существуют еще переменные $`, $& и $'. Perl не может решить, к какому регулярному выражению применяются эти переменные, и будет создавать копию целевого текста каждый раз, несмотря на отсутствие захватывающих скобок. По этой причине переменные $`, $& и $' называются "вредными". Кроме того, их применение замедляет работу программы.

Транслятор просматривает всю программу и все используемые ею модули на предмет наличия этих "вредных" переменных. И если он их не находит, то выпоняет оптимизацию программы: не создает копию целевого текста для регулярных выражений, которые не используют захватывающих скобок. Базовые модули, которые входят в поставку Perl, за исключением модуля English, не используют этих переменных.

"Вредные" переменные $`, $& и $' можно имитировать с помощью массивов @- и @+. (Предполагаем, что целевой текст находится в переменной $_ ):

  • $` соответствует substr($_, 0, $-[0])
  • $& соответствует substr($_, $-[0], $+[0] - $-[0])
  • $' соответствует substr($_, $+[0])
< Лекция 10 || Лекция 11: 123 || Лекция 12 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия