Поиск 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;
Это, конечно, не так красиво из-за того, что пришлось присваивать все найденные телефоны массиву.