2010-02-14 13 views
13

tengo una expresión regular:¿Cómo puedo almacenar capturas de una expresión regular de Perl en variables separadas?

/abc(def)ghi(jkl)mno(pqr)/igs 

¿cómo iba a capturar los resultados de cada paréntesis en 3 variables diferentes, uno 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); 
+0

¿Desea contar cuántas veces coincide el patrón? Eso es lo que me parece ... – Zaid

+0

necesito procesar las coincidencias – Incognito

Respuesta

14

su pregunta es un poco ambigua para mí, pero creo que quiere 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; 
} 
+0

Interesante. ¿Estás seguro de que eso funcionaría? – joejoeson

+3

que es un poco largo aliento. cuando se captura, puede usar referencias posteriores – ghostdog74

+4

ghostdog74: es una cuestión de gusto. Si realmente nombra sus variables $ first y $ second, entonces también podría usar $ 1 y $ 2, pero si les da nombres más descriptivos, puede mejorar la legibilidad para hacerlo así. –

0

Usted podría tener tres diferentes expresiones regulares de cada uno centrado 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.

2

@OP, cuando paréntesis son capturados, se pueden utilizar las variables $ 1, $ 2 .... estos son referencias hacia atrás

$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 
+3

Tenga en cuenta su uso del modificador g. Está haciendo una combinación global, así que supongo que quiere almacenar varias coincidencias. –

+2

Además, $ 1 y así sucesivamente no son "referencias", son capturas. Sin embargo, los paréntesis y las referencias posteriores están * relacionados *. – jrockway

3

Una forma alternativa de hacer que se vería como la respuesta de ghostdog74, pero usando una matriz que almacena referencias de 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 única estructura de datos, Y tener un buen bucle legible.

5

A partir de 5.10, puede utilizar named capture buffers así:

#!/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, se puede utilizar el siguiente lo que evita tener que añadir una línea para cada capturado búfer:

#!/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 única estructura de datos, por lo que es mejor volver a utilizar un hash. Esto requiere una matriz auxiliar, sin embargo:

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, si los nombres de las variables son muy first, second etc, o si los nombres de los tampones no importan pero sólo fin hace, puede utilizar :

my @data; 
if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x) { 
    push @{ $data[$_] }, $captured[$_] for 0 .. $#captured; 
} 
+0

¿Estás tratando de hacer una copia profunda en ese primer ejemplo? Me gustaría sacar el dclone de Storable. O eso, o su ejemplo necesita algún bucle para construir los valores que almacena en '$ data'. :) –

+0

@brian Estaba pensando en analizar un archivo en el que cada línea le da un 'primer' y un' segundo' y un 'tercer' valor y el almacenamiento de esos valores en sus propias matrices. Compare con el ejemplo de Leon Timmerman (http://stackoverflow.com/questions/2259784/how-can-i-store-captures-from-a-perl-regular-expression-into-separate-variables/2259795#2259795) –

Cuestiones relacionadas