Come posso memorizzare le acquisizioni da un'espressione regolare Perl in variabili separate?

StackOverflow https://stackoverflow.com/questions/2259784

Domanda

Ho una espressione regolare:

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

Come catturerei i risultati di ciascuna parentesi in 3 variabili diverse, una per ciascuna parentesi?In questo momento sto utilizzando un array per acquisire tutti i risultati, escono in sequenza ma poi devo analizzarli e l'elenco potrebbe essere enorme.

@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs);
È stato utile?

Soluzione

La tua domanda è un po 'ambiguo per me, ma penso che si vuole fare qualcosa di simile:

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;
}

Altri suggerimenti

A partire dalla versione 5.10 è possibile utilizzare buffer di acquisizione denominati anche:

#!/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;

Produzione:

$VAR1 = {
          'first' => [
                       'def'
                     ],
          'second' => [
                        'jkl'
                      ],
          'third' => [
                       'pqr'
                     ]
        };

Per le versioni precedenti, puoi utilizzare quanto segue per evitare di dover aggiungere una riga per ciascun buffer catturato:

#!/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;

Produzione:

$VAR1 = [
          'def'
        ];
$VAR2 = [
          'jkl'
        ];
$VAR3 = [
          'pqr'
        ];

Ma mi piace mantenere i dati correlati in un'unica struttura dati, quindi è meglio tornare a utilizzare un hash.Ciò richiede tuttavia un array ausiliario:

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;
}

Oppure, se i nomi delle variabili lo sono davvero first, second ecc., o se i nomi dei buffer non contano ma solo l'ordine, puoi usare:

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

Un modo alternativo per farlo sarebbe simile risposta di ghostdog74, ma utilizzando una matrice che memorizza i riferimenti di 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 il vantaggio principale qui di usare una singola struttura di dati, e avere un bel ciclo leggibile.

@OP, quando vengono catturate le parentesi, puoi utilizzare le variabili $1,$2....questi sono riferimenti all'indietro

$string="zzzabcdefghijklmnopqrsssszzzabcdefghijklmnopqrssss";
while ($string =~ /abc(def)ghi(jkl)mno(pqr)/isg) {
    print "$1 $2 $3\n";
}

produzione

$ perl perl.pl
def jkl pqr
def jkl pqr

Si potrebbe avere tre differenti espressioni regolari è ciascuno incentrato su gruppi specifici. Ovviamente, si desidera assegnare solo gruppi diversi per diverse matrici nel regex, ma penso che l'unica opzione è quella di dividere l'espressione regolare in su.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top