对于这篇长篇文章感到抱歉,对于Perl的退伍军人来说代码应该很容易理解。我是Perl的新手,我正在试图找出这段代码:
my %regression;
print "Reading regression dir: $opt_dir\n";
foreach my $f ( glob("$opt_dir/*.regress") ) {
my $name = ( fileparse( $f, '\.regress' ) )[0];
$regression{$name}{file} = $f;
say "file $regression{$name}{file}";
say "regression name $regression{$name}";
say "regression name ${regression}{$name}";
&read_regress_file( $f, $regression{$name} );
}
sub read_regress_file {
say "args @_";
my $file = shift;
my $href = shift;
say "href $href";
open FILE, $file or die "Cannot open $file: $!\n";
while ( <FILE> ) {
next if /^\s*\#/ or /^\s*$/;
chomp;
my @tokens = split "=";
my $key = shift @tokens;
$$href{$key} = join( "=", @tokens );
}
close FILE;
}
say
行是我添加到调试中的内容。
我的困惑是子程序read_regress_file
的最后一部分。看起来href
是来自my $href = shift;
行的引用。但是,我试图弄清楚传递的哈希是如何被引用的。
%regression
是密钥为$name
的哈希。代码读取的.regress
文件是简单文件,包含变量及其值,格式为:
var1=value
var2=value
...
所以它看起来像
行my $name = (fileparse($f,'\.regress'))[0];
将密钥创建为标量和行
$regression{$name}{file} = $f;
实际上将$name
变为哈希。
在我的调试行中
say "regression name $regression{$name}";
打印引用,例如
regression name HASH(0x7cd198)
但
say "regression name ${regression}{$name}";
打印一个名称,例如
regression name {filename}
大括号内的文件名。
然而,使用
say "regression name $$regression{$name}";
什么都不打印。
根据我的理解,看起来regression
是一个实际的哈希,但引用是嵌套的哈希,name
。
为什么我的deference测试行使用大括号工作,但另一种形式的解除引用($$
)不起作用?
另外,为什么名字在打印时仍然被大括号包围?我不应该取消引用$name
吗?
如果难以阅读,我很抱歉。我很困惑实际引用了哪个哈希,以及如果引用是嵌套哈希,如何使用它们。
答案 0 :(得分:2)
这是一个艰难的。您发现了一些非常笨拙的代码,它们显示了Perl中可能存在的错误,并且您对解除引用Perl数据结构感到困惑。标准Perl安装包括完整的文档集,我建议您查看perldoc perlreftut
,也可以在perldoc.com在线获取
最明显的是你正在编写非常老式的Perl。自14年前v5.8发布以来,使用&符号&
调用Perl子程序并未被视为良好做法
我不认为在第一个for
循环开始时需要超越你明确的实验线。一旦你理解了这一点,其余的应该遵循
say "file $regression{$name}{file}";
say "regression name $regression{$name}";
say "regression name ${regression}{$name}";
首先,在字符串中扩展数据结构引用是不可靠的。 Perl试图按照你的意思去做,但是如果没有意识到这一点就很容易写出一些含糊不清的东西。使用printf
通常要好得多,以便您可以单独指定嵌入值。例如
printf "file %s\n", $regression{$name}{file};
那说,你有问题。 $regression{$name}
访问密钥等于%regression
的哈希$name
元素。该值是对另一个哈希的引用,因此行
say "regression name $regression{$name}";
打印类似
的内容regression name HASH(0x29348b0)
你真的不想看
您的第一次尝试$regression{$name}{file}
访问具有密钥file
的辅助哈希的元素。这很好用
但${regression}{$name}
应与$regression{$name}
相同。它在字符串之外,但在${regression}
和{$name}
内部是单独处理的
这里有太多的问题让我开始猜测你被困在哪里,特别是在没有谈论具体细节的情况下。但是,如果我重写像这样的初始代码
,它可能会有所帮助my %regression;
print "Reading regression dir: $opt_dir\n";
foreach my $f ( glob("$opt_dir/*.pl") ) {
my ($name, $path, $suffix) = fileparse($f, '\.regress');
$regression{$name}{file} = $f;
my $file_details = $regression{$name};
say "file $file_details->{file}";
read_regress_file($f, $file_details);
}
我已将哈希引用复制到$file_details
并将其传递给子例程。你能看到%regression
的每个元素都被文件的名称键入,并且每个值都是对的引用,这个哈希包含read_regress_file
填充的值?
我希望这会有所帮助。这不是一个真正的语言基础教学论坛,所以我不认为我能做得更好
答案 1 :(得分:0)
我的理解是:
$regression{$name}
表示hashref,如下所示:
{ file => '...something...'}
因此,为了取消引用$regression{$name}
返回的hashref,你必须做类似的事情:
%{ $regression{$name} }
为了获得完整的哈希值。
为了获取哈希的文件属性,请执行以下操作:
$regression{$name}->{file}
希望这有帮助。