我尝试迭代包含其他哈希的哈希。
我收到错误:
全局符号“%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'});
}
所以我想在armv7
,i386
等循环中运行,然后将哈希映射发送到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
应该收到哈希所以我需要以某种方式将$ARCH_CODES{$arch}
转换为哈希而不是标量
我尝试与this answer: Perl:Access values of hash inside a hash类似但得到相同的错误
有什么想法吗?
答案 0 :(得分:2)
函数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 = @_;
以与上述相同的方式纠正它。
答案 1 :(得分:1)
以下是使用传递引用的类似方法。希望你觉得它很有用。
有几点:
在下面的示例代码中,在子例程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并参考以准确显示传递的内容。再次使用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>