Есть ли Perl-эквивалент Python re.findall / re.finditer (итерационные результаты регулярных выражений)? - PullRequest
6 голосов
/ 22 января 2009

В Python скомпилированные шаблоны регулярных выражений имеют findall метод , который выполняет следующие действия:

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

Какой канонический способ сделать это в Perl? Наивный алгоритм, который я могу придумать, заключается в следующем: «пока поиск и замена на пустую строку успешны, делайте [suite]». Я надеюсь, что есть более хороший способ. : -)

Заранее спасибо!

Ответы [ 3 ]

13 голосов
/ 22 января 2009

Используйте модификатор /g в вашем матче. Из руководства perlop:

Модификатор "/g" определяет глобальное сопоставление с образцом, то есть сопоставление как можно больше раз в строке. Как это ведет себя, зависит от контекста. В контексте списка он возвращает список подстрок, сопоставленных с любыми захватывающими скобками в регулярном выражении. Если круглых скобок нет, возвращается список всех совпадающих строк, как если бы вокруг всего шаблона были круглые скобки.

В скалярном контексте каждое выполнение "m//g" находит следующее совпадение, возвращает true, если оно совпадает, и false, если дальнейшее совпадение отсутствует. Положение после последнего совпадения можно прочитать или установить с помощью функции pos(); см. "pos" в perlfunc. Неудачное совпадение обычно сбрасывает позицию поиска в начало строки, но этого можно избежать, добавив модификатор "/c" (например, "m//gc"). Изменение целевой строки также сбрасывает позицию поиска.

7 голосов
/ 22 января 2009

Чтобы основываться на ответе Криса, вероятно, наиболее уместно включить регулярное выражение //g в цикл while, например:

my @matches;
while ( 'foobarbaz' =~ m/([aeiou])/g )
{
    push @matches, $1;
}

Вставка некоторых быстрых операций ввода-вывода Python:

>>> import re
>>> re.findall(r'([aeiou])([nrs])','I had a sandwich for lunch')
[('a', 'n'), ('o', 'r'), ('u', 'n')]

Чтобы получить что-то сопоставимое в Perl, конструкция может выглядеть примерно так:

my $matches = [];
while ( 'I had a sandwich for lunch' =~ m/([aeiou])([nrs])/g )
{
    push @$matches, [$1,$2];
}

Но в целом, какую бы функцию вы ни выполняли, вы, вероятно, можете выполнять ее внутри самого цикла while.

2 голосов
/ 22 января 2009

Отличная ссылка для начинающих с содержанием, аналогичным @ kyle : Учебник Perl: использование регулярных выражений

...