致以亲爱的社区。 p>
我正在尝试在perl中创建一个带有散列和调试标志的sub
,默认为零。但是我一直收到此错误Odd number of elements in hash assignment
。如果我不使用调试标志,它似乎工作。
感谢您的帮助。
代码:
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use POSIX qw(strftime);
#
#file2hash : read the file in k<file_name> e.g.=kconfig & kmem into hash table
#
sub file2hash {
my ($file) = @_;
open(my $data, '<', $file) or die "Could not open '$file' $!\n";
my %HoH;
my $key;
my $value;
my $who;
my $rec;
my $field;
#while ( my $line = <$data>) {
while ( <$data>) {
#print $line;
next unless (s/^(.*?):\s*//); # / turn off editor coloring
$who = $1;
#print $who;
$rec = {};
$HoH{$who} = $rec;
for $field ( split ) {
($key, $value) = split /=/, $field;
$rec->{$key} = $value;
}
}
return %HoH;
}
#
#end file2hash
#
#
#print out hash table in k<file_name> format
#
sub hash2print{
(my %HoH,my $debug) = @_;
#my ($debug)=@_||0;
#my %HoH = shift;
#my $debug = shift || 0;
my $family;
my $role;
for $family ( keys %HoH ) {
#print "$family\n";
for $role ( keys %{ $HoH{$family} } ) {
if ($debug){
print "family:$family\n";
print "role: $role\n";
}
print "$role=$HoH{$family}{$role}";
}
print "\n";
}
}
#
#end hash2print
#
sub dispatch{
my $inc= shift;
my $config_f = shift || "kconfig";
my $memory_f = shift || "kmem";
my %h2=&file2hash($config_f);
my %m2=file2hash($memory_f);
my $today=&getDate();
print "$today\n";
print "$inc\n";
my $inc_cnt = $m2{$today}{$inc} || -999999999;
print "$inc_cnt\n";
#my %config = shift;
#my %mem = shift;
#my $event = shift;
#print $m2{$inc}{$today};
}
sub getDate{
my $date = strftime "%m/%d/%Y", localtime; # "
#print $date;
return $date;
}
my %h2=&file2hash("kconfig");
my %m2=&file2hash("kmem");
&hash2print(%h2,1);
&hash2print(%m2,1);
#print &getDate();
#my $xcnt= &dispatch("event_c3_z2");
#&dispatch("event_c3_z2");
#print $xcnt;
测试文件1:
event_a1_x1: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=6
event_a1_x2: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=5
event_b2_y1: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=4
event_b2_y2: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=3
event_c3_z1: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=2
event_c3_z2: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=1
测试文件2:
201609230012: event_a1_x1=6
201609230744: event_a1_x2=5
201609230844: event_b2_y1=4
201609230342: event_b2_y2=3
201609230245: event_c3_z1=2
201609230100: event_c3_z2=1
答案 0 :(得分:2)
参数作为一个平面列表传递给函数。另一方面,可以为散列分配列表%h = qw(a b)
,其中连续元素形成键值对,$h{a}
为'b'
。因此,当哈希是第一个在函数中接收参数的变量时,它会挖掘所有这些变量。以下是关于函数如何返回的recent post,其中适用相同的故事。
所以一切都分配给哈希,剩下的标量也是如此。因此,哈希得到的元素多于预期,并以奇数个元素结束。
解决方案 - 在这种情况下,仅通过引用传递哈希,如Inferno的答案
sub hash2print{
my ($rHoH, $debug) = @_;
my %HoH = %$rHoH;
# ...
}
hash2print(\%h2, 1);
原则上最好通过引用传递列表,除非它们非常短。
通常,您可以先传递标量,然后传递哈希
sub hash2print{
my ($value, %HoH) = @_;
# ...
}
hash2print(1, %h2);
但是在你的情况下这不会发生,因为$debug
是可选的,如果我们在调用函数时将其遗漏,则哈希的第一个键将在$value
中结束。
其他一些评论
除非存在不可协商的原因,否则不要使用全局变量。声明范围很小。
您无需执行$rec = {};
,只需声明my $rec;
。
一般情况下,请勿将&
放在函数调用前,而只使用file2hash(...)
;
答案 1 :(得分:1)
您希望按值将哈希值传递给子例程,这会产生问题。尝试通过引用传递哈希%h2
(注意\
之前的%
):
&hash2print(\%h2, 1);
然后在您的子hash2print
中,您可以通过以下方式获取哈希:
sub hash2print {
(my $hashref, my $debug) = @_;
my %HoH = %$hashref; # dereference $hashref to get back the hash
...
如果你不理解它们背后的概念,你可以阅读有关参考文献here的更多信息。