arrays - ¿Cómo puedo almacenar capturas de una expresión regular de Perl en variables separadas?
regex regex-group (5)
@OP, cuando se capturan los paréntesis, puede usar las variables $ 1, $ 2 ... estas son referencias retrospectivas
$string="zzzabcdefghijklmnopqrsssszzzabcdefghijklmnopqrssss";
while ($string =~ /abc(def)ghi(jkl)mno(pqr)/isg) {
print "$1 $2 $3/n";
}
salida
$ perl perl.pl
def jkl pqr
def jkl pqr
Tengo una expresión regular:
/abc(def)ghi(jkl)mno(pqr)/igs
¿Cómo puedo capturar los resultados de cada paréntesis en 3 variables diferentes, una para cada paréntesis? En este momento estoy usando una matriz para capturar todos los resultados, salen secuenciales, pero luego tengo que analizarlos y la lista podría ser enorme.
@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs);
Podrías tener tres expresiones regulares diferentes, cada una centrada en grupos específicos. Obviamente, le gustaría asignar diferentes grupos a diferentes matrices en la expresión regular, pero creo que su única opción es dividir la expresión regular.
Tu pregunta es un poco ambigua para mí, pero creo que quieres hacer algo como esto:
my (@first, @second, @third);
while( my ($first, $second, $third) = $string =~ /abc(def)ghi(jkl)mno(pqr)/igs) {
push @first, $first;
push @second, $second;
push @third, $third;
}
Una forma alternativa de hacerlo sería la respuesta de ghostdog74, pero usando una matriz que almacena referencias hash:
my @results;
while( $string =~ /abc(def)ghi(jkl)mno(pqr)/igs) {
my ($key1, $key2, $key3) = ($1, $2, $3);
push @results, {
key1 => $key1,
key2 => $key2,
key3 => $key3,
};
}
# do something with it
foreach my $result (@results) {
print "$result->{key1}, $result->{key2}, $result->{key3}/n";
}
con la ventaja principal aquí de usar una sola estructura de datos, Y tener un buen bucle legible.
A partir de 5.10, también puede usar los búferes de captura con nombre :
#!/usr/bin/perl
use strict; use warnings;
my %data;
my $s = ''abcdefghijklmnopqr'';
if ($s =~ /abc (?<first>def) ghi (?<second>jkl) mno (?<third>pqr)/x ) {
push @{ $data{$_} }, $+{$_} for keys %+;
}
use Data::Dumper;
print Dumper /%data;
Salida:
$VAR1 = { ''first'' => [ ''def'' ], ''second'' => [ ''jkl'' ], ''third'' => [ ''pqr'' ] };
Para versiones anteriores, puede usar lo siguiente que evita tener que agregar una línea para cada buffer capturado:
#!/usr/bin/perl
use strict; use warnings;
my $s = ''abcdefghijklmnopqr'';
my @arrays = / my(@first, @second, @third);
if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {
push @{ $arrays[$_] }, $captured[$_] for 0 .. $#arrays;
}
use Data::Dumper;
print Dumper @arrays;
Salida:
$VAR1 = [ ''def'' ]; $VAR2 = [ ''jkl'' ]; $VAR3 = [ ''pqr'' ];
Pero me gusta mantener los datos relacionados en una sola estructura de datos, por lo que es mejor volver a usar un hash. Sin embargo, esto requiere una matriz auxiliar:
my %data;
my @keys = qw( first second third );
if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {
push @{ $data{$keys[$_]} }, $captured[$_] for 0 .. $#keys;
}
O bien, si los nombres de las variables son realmente el first
, el second
, etc., o si los nombres de los buffers no importan, pero solo el orden lo hace, puede usar:
my @data;
if ( my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {
push @{ $data[$_] }, $captured[$_] for 0 .. $#captured;
}