在 Perl 中引用哈希的哈希
Deferencing hash of hashes in Perl
抱歉这么长post,对于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
。
为什么我使用大括号的引用测试行有效,但其他形式的取消引用 ($$
) 不起作用?
另外,为什么打印出来的名字还是用大括号括起来?我不应该取消引用 $name
吗?
如果这难以阅读,我很抱歉。我很困惑实际引用了哪个散列,以及如果引用是嵌套散列如何引用它们。
我的理解是这样的:
$regression{$name}
代表一个hashref,看起来像这样:
{ file => '...something...'}
因此,为了取消引用 $regression{$name}
返回的 hashref,您必须执行以下操作:
%{ $regression{$name} }
为了得到完整的哈希。
为了得到散列的文件属性,这样做:
$regression{$name}->{file}
希望这对您有所帮助。
这是一个艰难的过程。您发现了一些非常笨拙的代码,这些代码显示了很可能是 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
的每个元素都以文件名作为键值,并且每个值都是 对 的引用 包含由 [= 填充的值的另一个哈希30=]?
希望对您有所帮助。这不是一个真正的语言基础教学论坛,所以我认为我不能做得更好
抱歉这么长post,对于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
。
为什么我使用大括号的引用测试行有效,但其他形式的取消引用 ($$
) 不起作用?
另外,为什么打印出来的名字还是用大括号括起来?我不应该取消引用 $name
吗?
如果这难以阅读,我很抱歉。我很困惑实际引用了哪个散列,以及如果引用是嵌套散列如何引用它们。
我的理解是这样的:
$regression{$name}
代表一个hashref,看起来像这样:
{ file => '...something...'}
因此,为了取消引用 $regression{$name}
返回的 hashref,您必须执行以下操作:
%{ $regression{$name} }
为了得到完整的哈希。
为了得到散列的文件属性,这样做:
$regression{$name}->{file}
希望这对您有所帮助。
这是一个艰难的过程。您发现了一些非常笨拙的代码,这些代码显示了很可能是 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
的每个元素都以文件名作为键值,并且每个值都是 对 的引用 包含由 [= 填充的值的另一个哈希30=]?
希望对您有所帮助。这不是一个真正的语言基础教学论坛,所以我认为我不能做得更好