Come posso utilizzare il valore di una variabile come un nome di variabile Perl? [duplicare]

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

Domanda

    

Questa domanda ha già una risposta qui:

         

Mi dispiace per tutte queste domande stupide, sono stato spinto in programmazione Perl e sto trovando davvero difficile pensare come un programmatore Perl.

domanda stupida per oggi: Carico un file delimitato pipe in un hash utilizzando il campo ID come la chiave, in questo modo

#open file

my %hash;
while (<MY_FILE>) {
    chomp;

    my ($id, $path, $date) = split /\|/;

    $hash{$id} = {
        "path" => $path,
        "date" => $date
    };
}

C'è un paio di volte, però, quando ho effettivamente bisogno la chiave per essere il percorso perché, per qualsiasi motivo (e no, non può essere modificato) l'id non è unico, così ho avuto la brillante idea che ho potuto mettere tutto in una subroutine e passare il nome della variabile da utilizzare come chiave ad esso, un po 'in questo modo:

load_hash("path");

sub load_hash {
    my $key = shift;

    #do stuff, and then in while loop
    $hash{${$key}} = #and so on
}

ma in perldb x $ {$ key} è sempre undef, anche se x $ {path} stampa il valore di $ percorso.

C'è un modo di fare quello che sto cercando di?

TIA

È stato utile?

Soluzione

Una cosa come questa?

use Carp 'confess';

sub load_hash {
    my $key = shift;

    # ...

    while (...) {
        # ...
        my %line;  # important that this is *inside* the loop
        @line{qw (id path date)} = split /\|/;
        confess "BUG: unknown key '$key'"  unless exists $line{$key};  # error checking
        $hash{$line{$key}} = \%line;
        delete $line{$key};  # assuming you don't want the key value duplicated
    }
}

Altri suggerimenti

Si sta cercando di usare "riferimenti simbolici". Se hai un problema e si pensa "hey, io risolvere questo con riferimenti simbolici" Ora avete due problemi.

In primo luogo, essi funzionano solo su variabili globali. Hai dichiarato $path come lessicale (visibili solo nel blocco che è stato dichiarato) e quindi load_path Non si può vedere. No, non fanno $path globale.

In secondo luogo, arbitri simbolici creano spaghetti code. Globali sono già abbastanza grave. Essi sono accessibili ovunque e in qualsiasi momento da qualsiasi cosa. Con un riferimento simbolico a una globale non si può anche vedere quale mondiale si accede. Questo rende impossibile per tenere traccia di ciò che potrebbe cambiare quello. Questo è il motivo per cui strict li si spegne. Accendere strict e lasciarlo acceso finché non si sa quando si dovrebbe spegnerlo.

Non sono del tutto sicuro di quello che stai cercando di realizzare, ma sembra questo va bene.

my %hash;
while (<MY_FILE>) {
    chomp;

    my ($id, $path, $date) = split /\|/;

    $hash{$path} = {
        "path" => $path,
        "date" => $date
    };
}

Ma avrei probabilmente spostare il parsing della linea in una funzione e lasciare l'incarico di hash per il ciclo principale. Analisi della riga è un chiaro pezzo di logica e totalmente separato dal assegnare la riga al file hash. Un buon segno è che %hash non deve essere globale.

my %hash;
while (<MY_FILE>) {
    my $line = parse_line($_);

    my $id = $line->{path};
    $hash{$id} = $line;
}


my @fields = qw(id path date);
sub parse_line {
    my $line = shift;
    chomp $line;

    my %data;
    # This is assigning to a hash slice.  Look it up, its handy.
    @data{@fields} = split m{\|}, $line;

    return \%data;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top