簡體   English   中英

防御Perl中的哈希哈希

[英]Deferencing hash of hashes in Perl

抱歉,這篇漫長的文章對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的最后一部分。 看來hrefmy $href = shift;行中的引用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嗎?

如果很難理解,對不起。 我很困惑實際引用了哪個哈希值,以及如果引用是嵌套哈希值時如何尊重它們。

這是困難的一個。 您已經找到了一些非常尷尬的代碼,這些代碼顯示了Perl中的錯誤,而對於取消引用Perl數據結構卻感到困惑。 標准Perl安裝包括完整的文檔集,我建議您看一下perldoc perlreftut ,也可以從perldoc.com在線獲得。

最明顯的是,您正在編寫非常老式的Perl。 使用符號&調用Perl子還沒有考慮好做法,因為V5.8是十四年前發布

我認為,在第一個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}訪問其鍵等於$name的哈希%regression元素。 該值是對另一個哈希的引用,因此該行

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 ,並且每個值都是另一個哈希的引用,該哈希包含由read_regress_file填充的值?

我希望這有幫助。 這實際上不是講語言基礎的論壇,所以我認為我不能做得更好

我了解的是:

$regression{$name} 

表示一個hashref,如下所示:

{ file => '...something...'}

因此,為了取消引用$regression{$name}返回的hashref,您必須執行以下操作:

%{ $regression{$name} }

為了獲得完整的哈希值。

為了獲得哈希的文件屬性,請執行以下操作:

$regression{$name}->{file}

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM