Практическое использование операторов m// и s///
5.5. Поиск n-ного совпадения
С модификатором g происходит поиск всех прототипов шаблона, но что делать, если нужно только вполне определенное, скажем, третье, совпадение? Здесь можно применить оператор цикла while:
use locale;
my $s='Тел. 2-3344. Другой тел. 3-2233, а вот еще один тел. 4-1122';
my $count=0;
while ($s =~ /тел\.\s+([\d-]+)/gi)
{ if (++$count == 3)
{ print "Третий номер: $1\n";
}
}Третий номер: 4-1122
В регулярном выражении мы захватываем в переменную $1 последовательность из цифр и знака минус, которая стоит после фрагмента "тел. ". Модификатор g обеспечивает поиск всех прототипов шаблона друг за другом, сохраняя в переменной $s смещение конца предыдущего совпадения. При очередном успехе оператор поиска возвращает единицу, что заставляет цикл while продолжать работать. После того, как будет найден последний номер телефона, оператор поиска вернет пустую строку, и оператор while закончит выполнение. Также можно было бы после печати третьего телефона поставить оператор last.
Модификатор i нужен, т.к. не все фрагменты "тел." набраны строчными буквами. Но тогда нужна русская локаль, чтобы модификатор i действовал также на русские буквы.
Иначе в этом примере совпадение начнется со второго телефонного номера и на печать ничего не выйдет.
С таким же успехом можно было использовать цикл for:
use locale;
my $s='Тел. 2-3344. Другой тел. 3-2233, а вот еще один тел. 4-1122';
for (my $count=0; $s =~ /тел\.\s+([\d-]+)/gi;)
{ if (++$count == 3)
{ print "Третий номер: $1\n";
last;
}
}Наконец, можно использовать встроенный код Perl, но тогда надо форсировать списочный контекст выполнения оператора поиска, чтобы поиск выполнялся итеративно под действием модификатора g, иначе после нахождения первого телефона поиск закончится:
use locale;
my $s='Тел. 2-3344. Другой тел. 3-2233, а вот еще один тел. 4-1122';
my $count=0;
my @a=$s =~ /тел\.\s+([\d-]+)
(?{
if (++$count == 3)
{ print "Третий номер: $1\n";
}
})/gix;Это, конечно, не так красиво из-за того, что пришлось присваивать все найденные телефоны массиву.
