Como posso usar o valor de uma variável como um nome de variável Perl? [duplicado]
-
19-09-2019 - |
Pergunta
Esta questão já tem uma resposta aqui:
Desculpe sobre todas essas perguntas tolas, eu fui arrastado para a programação Perl e estou achando muito difícil pensar como um programador de Perl.
Pergunta boba para hoje: Eu carregar um arquivo delimitado tubulação em um hash usando o campo id como a chave, como assim
#open file
my %hash;
while (<MY_FILE>) {
chomp;
my ($id, $path, $date) = split /\|/;
$hash{$id} = {
"path" => $path,
"date" => $date
};
}
Há algumas vezes, no entanto, quando eu realmente preciso a chave para ser o caminho, porque, por qualquer razão (e não, ele não pode ser alterado) o id não é única, então eu tive a brilhante ideia de que Eu poderia colocar tudo em uma sub-rotina e passar o nome da variável para usar como a chave para ela, tipo assim:
load_hash("path");
sub load_hash {
my $key = shift;
#do stuff, and then in while loop
$hash{${$key}} = #and so on
}
mas em perldb x {$ key} $ é sempre undef, embora x $ {path} imprime o valor em $ path.
Existe alguma maneira de fazer o que eu estou tentando?
TIA
Solução
Algo como isso?
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
}
}
Outras dicas
Você está tentando usar "referências simbólicas". Se você tem um problema e você pensa "hey, eu vou resolver isso com referências simbólicas" agora você tem dois problemas.
Em primeiro lugar, eles só funcionam em globals. Você declarou $path
como lexical (visível apenas no bloco que foi declarado) e, assim, LOAD_PATH não pode vê-lo. Não, não faça $path
global.
Em segundo lugar, refs simbólicos criar código espaguete. Globals são ruins o suficiente. Eles podem ser acessados ??em qualquer lugar, a qualquer hora por qualquer coisa. Com uma referência simbólica a um global, você não pode sequer ver qual global está sendo acessado. Isso torna impossível para acompanhar o que pode mudar o que. É por isso que strict
transforma-las. Ligue strict
e deixá-lo até que você sabe quando você deve desligá-lo.
Eu não sou inteiramente certo o que você está tentando realizar, mas parece que isso é bom.
my %hash;
while (<MY_FILE>) {
chomp;
my ($id, $path, $date) = split /\|/;
$hash{$path} = {
"path" => $path,
"date" => $date
};
}
Mas eu provavelmente mover a análise da linha em uma função e deixar a atribuição de hash para o loop principal. Analisando a linha é um pedaço clara da lógica e pode ser totalmente separado de atribuir a linha para o hash do arquivo. Um bom sinal é que %hash
não tem que ser global.
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;
}