2009-11-13 158 views
1

对于所有这些愚蠢的问题感到抱歉,我一直强调Perl编程,而且我发现很难像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

回答

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 
    } 
} 
+0

谢谢,工作。 – Sparkles 2009-11-13 00:57:26

10

您正在尝试使用“符号引用”。如果您遇到问题,并且您认为“嗨,我会用符号参考来解决这个问题”,您现在有两个问题。

首先,他们只适用于全局变量。您已将$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; 
} 
+0

别担心,我总是使用严格和警告(尽管在尝试此操作时我必须关闭警告)。 – Sparkles 2009-11-13 00:59:06

+3

@Sparkles,如果你不得不关闭警告,你可能做错了什么。 – 2009-11-13 04:50:07

+1

upvoted for引用最自以为是的Perl仇敌活着? (Naggum是最自以为是的Perl仇敌,但他死了。) – jrockway 2009-11-13 05:33:20