如何在Perl中的哈希数组中访问哈希

时间:2015-04-20 04:25:18

标签: arrays perl multidimensional-array hash

我有我认为是一个引用哈希数组的哈希。我想要了解的是如何访问这个哈希数组中的哈希元素。

编辑:这是完整的哈希结构

$VAR1 = {
      'CVE-2015-0677' => {
                         'vuln:references' => [
                                              {
                                                'attr' => {
                                                            'reference_type' => 'VENDOR_ADVISORY',
                                                            'xml:lang' => 'en'
                                                          },
                                                'vuln:source' => 'CISCO',
                                                'vuln:reference' => [
                                                                    {
                                                                      'attr' => {
                                                                                  'href' => 'http://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20150408-asa',
                                                                                  'xml:lang' => 'en'
                                                                                }
                                                                    }
                                                                  ]
                                              }
                                            ],
                         'vuln:published-datetime' => '2015-04-12T21:59:03.033-04:00',
                         'vuln:last-modified-datetime' => '2015-04-13T17:45:18.310-04:00',
                         'vuln:vulnerable-software-list' => [
                                                              'cpe:/o:cisco:adaptive_security_appliance_software:9.0.3',
                                                              'cpe:/o:cisco:adaptive_security_appliance_software:8.4.5',
                                                            ],
                         'vuln:summary' => 'The XML parser in Cisco Adaptive Security Appliance (ASA) Software 8.4 before 8.4(7.28), 8.6 before 8.6(1.17), 9.0 before 9.0(4.33), 9.1 before 9.1(6), 9.2 before 9.2(3.4), and 9.3 before 9.3(3), when Clientless SSL VPN, AnyConnect SSL VPN, or AnyConnect IKEv2 VPN is used, allows remote attackers to cause a denial of service (VPN outage or device reload) via a crafted XML document, aka Bug ID CSCus95290.'
                       }
    };

如果我尝试以下操作,则第一个Data :: Dumper输出的输出与第二个输出相同。

for my $key ( keys $hash ) {
 my @references =  $hash->{$key}{'vuln:references'};
 print Dumper(@references);  #1
  for my $vulnref (@references) {
    print Dumper($vulnref); #2
  }
}

#1
$VAR1 = [
       {
         'vuln:reference' => 'VENDOR',
         'vuln:source' => 'CISCO',
        }
        ];

#2  
$VAR1 = [
      {
        'vuln:reference' => 'VENDOR',
        'vuln:source' => 'CISCO',

      }
    ];

所以我的for循环似乎没有任何影响?

但是,如果我循环两次,那么第二次循环

for my $key ( keys $hash ) {
  my @references =  $hash->{$key}{'vuln:references'};
  print Dumper(@references); #1
  for my $vulnref (@references) {
    for my $vuln ($vulnref) {
       print Dumper($vuln);  #2
    }
   }
}


#1 
$VAR1 = [
       {
        'vuln:reference' => 'VENDOR',
        'vuln:source' => 'CISCO',

      }
    ];

#2
$VAR1 = {
       'vuln:reference' => 'VENDOR',
       'vuln:source' => 'CISCO', 
    };

我现在似乎正在访问哈希。

我相信我在这里缺少一些基本的东西。

非常感谢。

1 个答案:

答案 0 :(得分:1)

您没有显示散列的最高级别。您显示的$VAR1$hash->{key}的值,但我不知道key可能是什么。

无论如何,使用我所拥有的,

  • $hash->{key}是对哈希的引用,其中包含一个带有键vuln:references的单个元素

  • $hash->{key}{'vuln:references'}是对数组的引用,其中包含索引为零的单个元素

  • $hash->{key}{'vuln:references'}[0]是对另一个哈希的引用,这次使用两个元素

你没有说你想对这些数据做什么,但看起来你需要的只是

my $data = $hash->{key}{'vuln:references'}[0];

for my $key (keys %$data) {
  printf "%s => %s\n", $key, $data->{$key};
}

<强>输出

vuln:source => CISCO
vuln:reference => VENDOR

<强>更新

您没有说明如何定义$key,而是

for my $data ( $hash->{$key}{'vuln:references'} ) { ... }

你写了一个循环,执行一次$data设置为我上面描述的数组引用。

要遍历整个结构,假设$hash引用的最外面的哈希值和内部数组是唯一具有多个元素的图层,您可以编写

for my $cve ( keys %$hash ) {
  my $refs = $hash->{$cve}{'vuln:references'};
  print $cve, " \n";
  for my $ref ( @$refs ) {
    printf "  %s => %s\n", $_, $ref->{$_} for keys %$ref;
    print "\n";
  }
}

请注意keys %$hash@$refs%$ref中结构的解除引用。在更新版本的Perl中,您可以使用keys $hash而无需取消引用,但它是一项实验性功能,不应在实时代码中使用,如果您已use warnings,则会生成警告消息你应该(和use strict一起)在你的程序顶部

至于为什么你的代码转储相同的值两次,你有

my @references = $hash->{$key}{'vuln:references'};

将数组@references设置为保存一个元素,这是该点哈希的数组引用。然后

print Dumper(@references);

逐个转储数组的每个元素。因为只有一个元素,所以它只输出一个转储。最后

for my $vulnref (@references) {
  for my $vuln ($vulnref) {
    print Dumper($vuln);
  }
}

$vulnref设置为@references的每个元素。因为只有一个循环执行一次,$vulnref设置为数组引用。然后$vuln设置为列表( $vulnref )的每个元素,因此它需要同一参考的另一个副本。最后转储该值,结果显示与之前相同的数组引用。

请记住,Perl标量值以$开头;即使数组的元素是$array[0],它也被视为单值,即使该值是引用。如果您想访问它引用的数据,您必须使用适当的符号取消引用