Как я могу хранить регулярные выражения в массиве в Perl? - PullRequest
62 голосов
/ 21 февраля 2010

Я пытаюсь использовать регулярные выражения в Perl. Что мне было интересно, было ли возможно сохранить все совпадения с выражением в массиве? Я знаю, что могу использовать следующее: ($1,...,$n) = m/expr/g;, но кажется, что это можно использовать, только если вы знаете количество совпадений, которое вы ищете. Я пробовал my @array = m/expr/g;, но, похоже, это не сработало.

Спасибо за вашу помощь!

Ответы [ 5 ]

75 голосов
/ 21 февраля 2010

Если вы делаете глобальное совпадение (/g), тогда регулярное выражение в контексте списка вернет все захваченные совпадения. Просто сделайте:

my @matches = ( $str =~ /pa(tt)ern/g )

Эта команда, например:

perl -le '@m = ( "foo12gfd2bgbg654" =~ /(\d+)/g ); print for @m'

Дает вывод:

12
2
654
17 голосов
/ 21 февраля 2010

Иногда вам нужно получить все совпадения по всему миру, как это делает preg_match_all в PHP. Если это ваш случай, то вы можете написать что-то вроде:

# a dummy example
my $subject = 'Philip Fry Bender Rodriguez Turanga Leela';
my @matches;
push @matches, [$1, $2] while $subject =~ /(\w+) (\w+)/g;

use Data::Dumper;
print Dumper(\@matches);

Он печатает

$VAR1 = [
          [
            'Philip',
            'Fry'
          ],
          [
            'Bender',
            'Rodriguez'
          ],
          [
            'Turanga',
            'Leela'
          ]
        ];
17 голосов
/ 21 февраля 2010

См. Запись для perldoc perlop в разделе «Соответствие в контексте списка»:

Если параметр / g не используется, m // в контексте списка возвращает список, состоящий из подвыражения, соответствующие скобкам в шаблоне, то есть ($ 1, $ 2, $ 3 ...)

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

Вы можете просто получить все совпадения, присвоив массив или выполнив оценку в контексте списка:

my @matches = ($string =~ m/word/g);
8 голосов
/ 11 декабря 2012

Я думаю, это очевидный пример. Примечание * Модификатор /g в первом регулярном выражении:

$string = "one two three four";

@res = $string =~ m/(\w+)/g;
print Dumper(@res); # @res = ("one", "two", "three", "four")

@res = $string =~ m/(\w+) (\w+)/;
print Dumper(@res); # @res = ("one", "two")

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

($one, $two) = $string =~ m/(\w+) (\w+)/;
0 голосов
/ 28 мая 2019

Обратите внимание, что если вы знаете количество групп захвата, которое вам нужно на совпадение, вы можете использовать этот простой подход, который я представляю в качестве примера (из 2 групп захвата).

Предположим, у вас есть некоторые "данные", такие как

my $mess = <<'IS_YOURS';
Richard     Rich
April           May
Harmony             Ha\rm
Winter           Win
Faith     Hope
William         Will
Aurora     Dawn
Joy  
IS_YOURS

со следующим регулярным выражением

my $oven = qr'^(\w+)\h+(\w+)$'ma;  # skip the /a modifier if using perl < 5.14

Я могу захватить все 12 (6 пар, , а не 8 ... Гармония сбежала и Джой отсутствует) в @box ниже.

my @box = $mess =~ m[$oven]g;

Если я хочу «разобрать» детали коробки, я мог бы просто сделать:

my %hash = @box;

Или я мог просто пропустить коробку целиком,

my %hash = $mess =~ m[$oven]g;

Обратите внимание, что %hash содержит следующее. Порядок утерян, и двойные ключи (если таковые существовали) сдавлены:

(
          'April'   => 'May',
          'Richard' => 'Rich',
          'Winter'  => 'Win',
          'William' => 'Will', 
          'Faith'   => 'Hope',
          'Aurora'  => 'Dawn'
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...