【问题标题】:hash inside hash, fails to fetch data散列内的散列,无法获取数据
【发布时间】:2016-12-12 17:43:38
【问题描述】:

我尝试遍历包含其他哈希的哈希。

我得到错误:

全局符号“%arch_”需要明确的包名

这是一个代码:

my %ARCH_CODES = (
    armv7  => {id  => 102, desc => "aaaaaa"},
    i386   => {id  => 103, desc => "bbbbbb"},
    x86_64 => {id  => 104, desc => "cccccc"},
    arm64  => {id  => 105, desc => "dddddd"}
);

sub af_exit
{
    my %_error = @_;
    writeLogAndPrint($_error{'id'});
    exit($_error{'id'});
}

所以我想在armv7i386 等上循环运行并将哈希映射发送到af_exit

for my $arch_ (keys %ARCH_CODES) {
       foo($ARCH_CODES{$arch_}); 
       # tried foo(%{ $ARCH_CODES{$arch_} } ) 
    } 

问题发生在foo 方法中:

sub foo
{
   my %arch = @_; # here I get an ERROR: Global symbol "%arch_" requires explicit package name
     my $res = runCommand("file zzz | grep \"$arch{id})\"");
     af_exit($ARCH_CODES{$arch});
   }
}

第二个问题是 af_exit 应该接收 hash 所以我需要以某种方式将 $ARCH_CODES{$arch} 转换为 hash 而不是标量

我尝试制作类似于this answer: Perl:Access values of hash inside a hash 但得到相同的错误

有什么想法吗?

【问题讨论】:

  • $ARCH_CODES{$arch_} 是一个包含值 => {id => 102, desc => "aaaaaa"} 的哈希引用,您可以使用 my $arch = @_ 获取哈希引用,然后像 foreach my $keys ( keys %$arch ) 一样访问此哈希引用
  • @AbhiNickz 但在这种情况下我不能使用af_exit($ARCH_CODES{$arch});
  • 您可以使用af_exit($arch);,它将hash 引用发送给子,然后您可以像my $_error = @_; 一样再次使用它
  • my %_error = @_; 更改为 my %_error = %{$_[0]};

标签: perl


【解决方案1】:

函数foo 正在获取一个hashref

foo( $ARCH_CODES{$arch_} );

因为%ARCH_CODES 的值是哈希引用,而它需要一个哈希

sub foo
{
    my %arch = @_;
    # ...
}

因此,您尝试将具有单个标量 (hashref) 的列表分配给哈希。为此,如果您有警告,您会收到警告Odd number of elements in hash assignment,这将直接导致您出现错误。

更改 foo 使其采用该标量

my ($rarch) = @_;

然后要么使用引用$rarch,要么在子my %arch = %$rarch 中创建一个新的哈希,并保持函数的其余代码不变。

或者您可以将哈希传递给函数foo( %{$ARCH_CODES{$arch_}} ),其余代码保持原样。一般来说,我更喜欢通过引用传递长列表和复杂的数据结构。

当您使用参考 ($rarch) 时,对它的任何更改都会更改它作为参考的数据。这使我们能够有效地更改调用者的数据。另一方面,当你在 sub 中取消引用它时,你会得到一个本地副本。这更安全,因为对它的意外更改(错误)不会影响调用者。

永远use warnings;


当您调用af_exit 时重复相同的错误,并传递一个 hashref

af_exit($ARCH_CODES{$arch});

虽然它需要一个哈希

sub af_exit
{
     my %_error = @_;

改正方法同上。

【讨论】:

  • @snaggs 我编辑了答案(添加了另外两种方法),如果有更多帮助,请告诉我。
【解决方案2】:

这是使用传递引用的类似方法。希望对您有用。

几点:

  1. 在您的 foreach 循环和子 foo 中,您传递的是标量而不是哈希引用。
  2. 您还可以使用 shift 在子例程中接收输入,然后取消引用变量以检索值。

在下面的示例代码中,在子程序 foo 中,我正在执行虚拟操作以将哈希映射传递给 af_exit,仅当 id 为 102 或 104 时,仅作为示例。

这里我关闭了 Data::Dumper 输出,也没有打印子例程接收到的值的引用类型。我们稍后会看到。

#!/usr/bin/perl

use strict ;
use warnings  ;
use Data::Dumper ;

my %ARCH_CODES = (
    armv7  => {id  => 102, desc => "aaaaaa"},
    i386   => {id  => 103, desc => "bbbbbb"},
    x86_64 => {id  => 104, desc => "cccccc"},
    arm64  => {id  => 105, desc => "dddddd"}
);

sub af_exit
{
        my $error = shift ;
        my $ref = ref $error ;
        #print "af_exit got variable which is of type $ref. Below is the Data Dumper output\n" ;
        #print Dumper $error ;
        print "${$error}{'id'}\n" ;
        #exit($$error{'id'});
        print "af_exit will perform exit on \[$$error{'id'}\]\n" ;
}

sub foo
{
        my $arch = shift ;
        my $ref = ref $arch ;
        #print "af_exit got variable which is of type $ref. Below is the Data Dumper output\n" ;
        #print Dumper $arch ;
        #my $res = runCommand("file zzz | grep \"$arch{id})\"");
        if ($$arch{id} == 102 || $$arch{id} == 104)
        {

                af_exit(\%$arch);
        }
}

for my $arch_ (keys %ARCH_CODES)
{
       foo(\%{$ARCH_CODES{$arch_}}) ;
}

结果:

%_04:04:54|root@[goat]:/home/ec2-user/cpp/study/temp> ./test
104
af_exit will perform exit on [104]
102
af_exit will perform exit on [102]
%_04:04:56|root@[goat]:/home/ec2-user/cpp/study/temp>

您始终可以使用 Data::Dumper 和 ref 来准确显示正在传递的内容。打开 Dumper 和参考输出,再次查看下面的结果。

%_04:09:19|root@[goat]:/home/ec2-user/cpp/study/temp> ./test
af_exit got variable which is of type HASH. Below is the Data Dumper output
$VAR1 = {
          'desc' => 'cccccc',
          'id' => 104
        };
af_exit got variable which is of type HASH. Below is the Data Dumper output
$VAR1 = {
          'desc' => 'cccccc',
          'id' => 104
        };
104
af_exit will perform exit on [104]
af_exit got variable which is of type HASH. Below is the Data Dumper output
$VAR1 = {
          'desc' => 'dddddd',
          'id' => 105
        };
af_exit got variable which is of type HASH. Below is the Data Dumper output
$VAR1 = {
          'desc' => 'aaaaaa',
          'id' => 102
        };
af_exit got variable which is of type HASH. Below is the Data Dumper output
$VAR1 = {
          'desc' => 'aaaaaa',
          'id' => 102
        };
102
af_exit will perform exit on [102]
af_exit got variable which is of type HASH. Below is the Data Dumper output
$VAR1 = {
          'desc' => 'bbbbbb',
          'id' => 103
        };
%_04:09:21|root@[goat]:/home/ec2-user/cpp/study/temp>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-07
    • 2013-07-13
    • 2012-10-27
    • 2018-06-29
    • 2013-07-08
    • 1970-01-01
    • 2013-04-14
    • 2023-03-11
    相关资源
    最近更新 更多