Регулярное выражение Perl, сортировка групп с несколькими совпадениями в соответствующие массивы

#regex #perl

#регулярное выражение #perl

Вопрос:

Итак, я разделил оператор с использованием регулярных выражений на 3 группы.

Группа 1: Моя собака любит гулять, Моя кошка любит купаться, Моя черепаха любит вздремнуть.

Группа 2: (. *) слова между «my» и «likes»

Группа 3: (. *) последние три слова после «для»

 #original statement
$p = "My dog likes to go for a walk
    My cat likes to go for a swim
    My turtle likes to go for a nap"

#regular expression used
$p =~ /((^My (.*) likes to go for a(.*)))/gm);
  

Массив 1: [«Моя собака любит гулять», «Моя кошка любит купаться», «Моя черепаха любит вздремнуть»]

Массив 2: [«собака», «кошка», «черепаха»]

Массив 3: [«прогулка», «сон», «плавание»]

Нужна помощь в размещении каждой группы в этих соответствующих массивах

Комментарии:

1. помещение каждой группы в соответствующие массивы.

2. группа 2 и группа 3, каждая из (.*)

3. группирует группы, разделенные круглыми скобками, и каждая группа имеет соответствующее совпадение, которое обозначается как $ 1, $ 2, $ 3

Ответ №1:

 use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $p = "
    My dog likes to go for a walk
    My cat likes to go for a swim
    My turtle likes to go for a nap
";
    
my $re = qr/(My (S ) likes to go for a (S ))/;
my $count = 0;
my @arrays;

(
   $arrays[0][$count],
   $arrays[1][$count], 
   $arrays[2][$count  ]
 ) = ($1,$2,$3) while $p =~ /$re/gm;

say Dumper(@arrays);

  

Вывод

 $VAR1 = [
          [
            'My dog likes to go for a walk',
            'My cat likes to go for a swim',
            'My turtle likes to go for a nap'
          ],
          [
            'dog',
            'cat',
            'turtle'
          ],
          [
            'walk',
            'swim',
            'nap'
          ]
        ];
  

Если по какой-либо причине OP по-прежнему предпочитает отдельные массивы вместо AoA, тогда код немного отличается

 use strict;
use warnings;
use feature 'say';

my $p = "
    My dog likes to go for a walk
    My cat likes to go for a swim
    My turtle likes to go for a nap
";
    
my $re = qr/(My (S ) likes to go for a (S ))/;
my $count = 0;
my(@array_1,@array_2,@array_3);

(
   $array_1[$count],
   $array_2[$count], 
   $array_3[$count  ]
 ) = ($1,$2,$3) while $p =~ /$re/gm;

say '-- Array 1 --';
say for @array_1;
say '-- Array 2 --';
say for @array_2;
say '-- Array 3 --';
say for @array_3;
  

Вывод

 -- Array 1 --
My dog likes to go for a walk
My cat likes to go for a swim
My turtle likes to go for a nap
-- Array 2 --
dog
cat
turtle
-- Array 3 --
walk
swim
nap
  

Ответ №2:

 my (@array1, @array2, @array3);
while ( $p =~ /^(My (.*) likes to go for a (.*))/gm ) {
   push @array1, $1;
   push @array2, $2;
   push @array3, $3;
}
  

Избежать глобальных переменных можно сделать следующим образом:

 my (@array1, @array2, @array3);
for my $line (split /n/, $p)
   if ( my ($pet, $verb) = /^My (.*) likes to go for a (.*)/ ) {
      push @array1, $line;
      push @array2, $pet;
      push @array3, $verb;
   }
}
  

Параллельные массивы немного громоздки. Подход AoA является более распространенным.

 my @array;
for my $line (split /n/, $p)
   if ( my ($pet, $verb) = /^My (.*) likes to go for a (.*)/ ) {
      push @array, [ $line, $pet, $verb ];
   }
}