Именованное сохранение

Вы можете сохранить части совпавшей строки при помощи круглых скобок, а затем использовать переменные $1, $2 и т. д. для работы с частичными совпадениями. Следить за этими нумерованными переменными и их содержимым непросто даже для элементарных шаблонов. Следующее регулярное выражение пытается найти два имени в строке $names:

use 5.010;
my $names = 'Fred or Barney';
if( $names =~ m/(\w+) and (\w+)/ ) { # Нет совпадения
say "I saw $1 and $2";
}

Мы не видим сообщения от say, потому что в строке вместо and стоит or. Чтобы поиск мог производиться в обоих вариантах, мы изменяем регулярное выражение и включаем альтернативу для and и or; для группировки альтернативы используются круглые скобки: use 5.010;

my $names = 'Fred or Barney';
if( $names =~ m/(\w+) (and|or) (\w+)/ ) { # Теперь совпадение есть
say "I saw $1 and $2";
}

Ой! Теперь сообщение выводится, но в нем нет второго имени, потому что в выражении появилась новая пара сохраняющих круглых скобок. В $2 хранится совпадение альтернативы, а второе имя оказалось в переменной $3 (которая не выводится):

I saw Fred and or

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


Представьте, насколько усложнится задача при большом количестве сохранений. Вместо того чтобы запоминать числа вида $1, Perl 5.10 позволяет нам задать имя сохраняемого частичного совпадения прямо в регулярном выражении. Совпавший текст сохраняется в хеше с именем %+: ключом является метка (то есть имя совпадения), а значением – совпавшая часть строки. Метка назначается конструкцией вида (?<МЕТКА>ШАБЛОН), где МЕТКА заменяется нужным именем. Первому частичному совпадению присваивается метка name1, второму – name2, а для получения их значений используются конструкции $+{name1} и $+{name2}:

use 5.010;
my $names = 'Fred or Barney';
if( $names =~ m/(?\w+) (?:and|or) (?\w+)/ ) {
say "I saw $+{name1} and $+{name2}";
}

Теперь программа выводит правильное сообщение:

I saw Fred and Barney

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

use 5.010;
my $names = 'Fred or Barney';
if( $names =~ m/((?\w+) (and|or) (?\w+))/ ) {
say "I saw $+{name1} and $+{name2}";
}

Итак, частичные совпадения помечены; теперь необходим способ обращения к ним в обратных ссылках.


Ранее мы уже встречали обратные ссылки вида \1 или \g{1}. Для помеченных групп используется синтаксис вида \g{метка}:

use 5.010;
my $names = 'Fred Flinstone and Wilma Flinstone';
if( $names =~ m/(?\w+) and \w+ \g{last_name}/ ) {
say "I saw $+{last_name}";
}

То же самое можно сделать и в другом синтаксисе. Вместо записи
\g{метка} используется запись \k<метка>:

use 5.010;
my $names = 'Fred Flinstone and Wilma Flinstone';
if( $names =~ m/(?\w+) and \w+ \k/ ) {
say "I saw $+{last_name}";
}

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Perl на эту тему:
Автоматические переменные совпадения
Границы слов
Добавление пропусков (/x)
Другие модификаторы
Жизненный цикл переменных частичных совпадений