Как я могу хранить регулярные выражения в массиве в Perl?

55

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

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

  • 9
    объяснить "не похоже на работу", желательно с реальным примером. это должно работать.
Теги:
arrays

4 ответа

66
Лучший ответ

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

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

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

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

Выдает вывод:

12
2
654
  • 10
    нет необходимости в (), = ~ является оператором с высоким приоритетом
  • 3
    Обязательно используйте ", если вы попробуете это в Windows 'shell', например, perl -le" @m = ('foo12gfd2bgbg654' = ~ / (\ d +) / g); напечатайте для @m «в противном случае вы получите ошибку, так как оболочка использует» в качестве разделителя строк
Показать ещё 1 комментарий
16

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

# 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'
          ]
        ];
  • 3
    Очень удобная техника; Есть ли способ обобщить это, если число групп захвата неизвестно? Похоже, вам может понадобиться специальная переменная массива, которая содержит ( $1, $2, ...) , но я не смог найти такую вещь.
14

См. руководство пользователя perldoc perlop в разделе "Согласование в контексте списка":

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

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

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

my @matches = ($string =~ m/word/g);
8

Я думаю, что это объяснительный пример. Обратите внимание, что модификатор /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+)/;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню