如何使用变量的值作为 Perl 变量名?[复制]
-
19-09-2019 - |
题
这个问题在这里已经有答案了:
- 在 Perl 中如何使用变量作为变量名? 3 个回答
对所有这些愚蠢的问题感到抱歉,我已经陷入 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
解决方案
像这样的东西吗?
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
}
}
其他提示
您正在尝试使用“符号引用”。如果您遇到问题并且认为“嘿,我会用符号引用解决这个问题”,那么您现在有两个问题。
首先,它们只适用于全局变量。你已经声明了 $path
作为词法(仅在声明它的块中可见),因此 load_path 看不到它。不,不要做 $path
全球的。
其次,符号引用会创建意大利面条式代码。全局变量已经够糟糕的了。它们可以随时随地通过任何东西访问。通过对全局的符号引用,您甚至无法看到正在访问哪个全局。这使得追踪什么可能改变什么变得不可能。这就是为什么 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;
}
不隶属于 StackOverflow