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

Практическое использование операторов m// и s///

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >

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;

Это, конечно, не так красиво из-за того, что пришлось присваивать все найденные телефоны массиву.

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия