对于所有这些愚蠢的问题感到抱歉,我已经深入研究Perl编程,我发现很难像Perl程序员那样思考。
今天愚蠢的问题: 我使用id字段作为键将管道分隔文件加载到哈希中,如此
#open file
my %hash;
while (<MY_FILE>) {
chomp;
my ($id, $path, $date) = split /\|/;
$hash{$id} = {
"path" => $path,
"date" => $date
};
}
然而,有几次,当我真正需要键作为路径时,因为无论出于何种原因(并且不能,它无法更改),id不是唯一的,所以我有一个明智的想法,我可以把它全部放到子程序中并传递变量的名称作为它的关键,有点像:
load_hash("path");
sub load_hash {
my $key = shift;
#do stuff, and then in while loop
$hash{${$key}} = #and so on
}
但是在perldb中,x $ {$ key}始终是undef,尽管x $ {path}在$ path中打印了值。
有没有办法做我想做的事情?
TIA
答案 0 :(得分:10)
您正在尝试使用“符号引用”。如果你遇到问题并且你认为“嘿,我会用符号引用解决这个问题”你现在有两个问题。
首先,它们只适用于全局变量。您已将$path
声明为词法(仅在声明的块中可见),因此load_path无法看到它。不,不要让$path
全球化。
其次,符号引用创建意大利面条代码。全球足够糟糕。它们可以随时随地访问。通过对全局的符号引用,您甚至无法看到正在访问的WHICH全局。这使得无法追踪可能会改变的内容。这就是strict
将其关闭的原因。打开strict
并保持打开,直到知道何时应将其关闭。
我不完全确定你想要完成什么,但似乎这很好。
my %hash;
while (<MY_FILE>) {
chomp;
my ($id, $path, $date) = split /\|/;
$hash{$path} = {
"path" => $path,
"date" => $date
};
}
但我可能会将该行解析为一个函数,并将哈希赋值保留给主循环。解析该行是一个明显的逻辑块,可以完全分离将行分配给文件哈希。一个好的迹象是%hash
不一定是全球性的。
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;
}
答案 1 :(得分:2)
这样的东西?
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
}
}