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

Вы можете сохранить части совпавшей строки при помощи круглых скобок, а затем использовать переменные $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/(?<name1>\w+) (?:and|or) (?<name2>\w+)/ ) {
say "I saw $+{name1} and $+{name2}";
}


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

I saw Fred and Barney


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

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


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

use 5.010;
my $names = 'Fred Flinstone and Wilma Flinstone';
if( $names =~ m/(?<last_name>\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/(?<last_name>\w+) and \w+ \k<last_name>/ ) {
say "I saw $+{last_name}";
}
Теги:
регулярные выражения
Добавлено: 20 Июля 2018 19:26:14 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...