给出以下代码
#!/usr/bin/perl
use Data::Dumper;
my %hash;
my @colos = qw(ac4 ch1 ir2 ird kr3);
foreach my $colo (@colos) {
if(exists $hash{output}{$colo}) {
print "$colo is in the hash\n";
}
}
print Dumper(\%hash);
我创建了一个空哈希。我有一个数组,里面有几个缩写。如果我遍历数组以查看这些人是否在哈希中,则没有任何内容显示给STDOUT,这是预期的但是由于某种原因创建了$ hash {output}。这根本不符合逻辑。我所做的只是存在。我哪里出错了?
答案 0 :(得分:7)
exists
查找给定哈希中的哈希元素。您的代码自动生成散列
%{ $hash{output} }
并检查该哈希中是否存在密钥为$colo
的哈希元素。
尝试以下方法:
if(exists $hash{output}{$colo}) {
更改为
if(exists $hash{output} and exists $hash{output}{$colo}) {
当然,您可以编写一个隐藏代码复杂性的子代码。
答案 1 :(得分:3)
Perl创建它,因为exists
测试指定的最后一个键,它不会递归测试。如果您改为:
if( exists $hash{output} && exists $hash{output}{$colo} ) {
但是为什么你还需要额外的钥匙呢?为什么不只是$hash{$colo}
?此外,如果您use strict
,则会在$hash
中收到有关未初始化值的警告。
答案 2 :(得分:3)
你已经有了一些很好的答案,但是,如果你想了解更多关于这种行为的信息,它通常被称为“autovivification”,并且有一个CPAN module可以禁用它,如果你愿意的话不会发生。
答案 3 :(得分:1)
实际的代码/哈希更复杂。哈希是:$ rotation_hash {output} {oor} {$ colo} {$ type} {$ hostname} {file} {$ filename} =< html_status_code>
正如其他人所说,当您询问是否存在$foo{bar}{fubar}
时,Perl会自动创建$foo{bar}
以测试$foo{bar}{fubar}
是否存在。如果您想阻止这种情况,则必须进行测试以查看$foo{bar}
是否存在,如果存在,则测试$foo{bar}{fubar}
是否存在。
然而,引起我注意的是你的七层哈希。当您的数据结构开始变得复杂时,您应该真正使用Perl面向对象的编码。我知道很多人都被Perl反对的导向编程所吓倒,但Perl可能是人们获取OOP最简单的语言之一。
如果没有别的,您使用OOP的原因与使用use strict;
的原因相同。当我use strict;
时,Perl会轻松拾取我在一个地方使用$foobar
作为变量的位置,但在其他地方将其称为$fubar
。您会因复杂的数据结构而失去保护。例如,您可以将$rotation_hash{output}{oor}
放在一个位置,但$rotation_hash{oor}{output}
放在另一个位置,而use strict
则无法捕捉到它。但是,如果你通过package
声明对象,并使用子程序作为方法和构造函数,那么你可以获得它。
面向对象的设计还可以帮助您消除跟踪数据结构的需要。对象为您处理这些,您可以专注于编码。而且,您不必创建多个文件。您只需将对象定义附加到文件的底部即可。