Perl脚本中$mapA哈希的Success/Failure计数异常求助
Perl哈希计数问题:无法正确获取$mapA{$Brand_Name}->{Success}和$mapA{$Brand_Name}->{Failure}的计数
我看了你的Perl脚本,核心问题出在遍历哈希时错误引用了旧变量,导致所有品牌的计数都指向最后一个处理的品牌,自然没法得到正确的结果。下面一步步帮你解决:
1. 找出关键错误
在你用each或者keys遍历%mapA的时候,一直用$Brand_Name来访问哈希值,但这个变量是之前读取CSV行时的最后一个品牌名称,并不是当前循环的键。比如这段代码:
while (($keyA)=each (%mapA)){ my $success= $mapA{$Brand_Name}->{Success}; # 错误!应该用当前循环的$keyA my $failure= $mapA{$Brand_Name}->{Failure}; # 错误!应该用当前循环的$keyA print "$keyA $mapA{$Brand_Name}->{Failure}++ $mapA{$Brand_Name}->{Success}++ \n"; }
你遍历拿到的是$keyA,但访问哈希时却用了旧的$Brand_Name,这就导致所有输出都指向最后一个品牌的计数。
2. 修复遍历代码
把所有遍历哈希时的$Brand_Name替换成当前循环的键($keyA或者$name):
修复each循环:
while (($keyA)=each (%mapA)){ my $success= $mapA{$keyA}->{Success}; my $failure= $mapA{$keyA}->{Failure}; print "$keyA 失败: $failure 成功: $success \n"; }
修复keys循环:
foreach my $name ( keys %mapA) { print "$name 失败: $mapA{$name}->{Failure} \n"; print "$name 成功: $mapA{$name}->{Success} \n"; print "$name 总统计:成功 $mapA{$name}->{Success} | 失败 $mapA{$name}->{Failure} \n"; }
3. 其他需要注意的细节
- 变量
$Streamz_Sent没有被使用,可以直接删除,避免冗余代码。 - 检查
$failureA='{error:MismatchSenderId}'是否和CSV文件中的错误字符串完全匹配(比如有没有额外空格、引号)。如果CSV里的字段被引号包裹,你的匹配就会失败,可以加一行调试代码确认:
print "Debug: 当前GoogleResA值为 '$GoogleResA'\n";
- 你开头重定向了STDOUT到
/root/Basavaraj/STREAMZ_GCM_APK.txt,所以所有print内容都会写到这个文件里,而不是控制台,这点要留意。
4. 替代的计数写法(可选)
如果你觉得嵌套哈希的写法有点繁琐,也可以用更简洁的方式初始化计数:
# 不需要提前初始化,Perl会自动为不存在的键创建并设为0后自增 if ($GoogleResA eq $failureA) { $mapA{$Brand_Name}->{Failure}++; } else { $mapA{$Brand_Name}->{Success}++; } # 注:如果$Brand_Name不存在,Perl会自动创建这个键,对应的Success/Failure会从0开始自增
修复后的完整代码
#!/usr/bin/perl use Text::CSV; use POSIX qw(strftime); use Data::Dumper; use LWP::Simple; my $APK_GCM="/root/Basavaraj/GCM/cdr_02-01-2018_StreamzGcm.csv"; my $WEB_GCM="/root/Basavaraj/GCM/cdr_02-01-2018_StreamzWebPushNotification.csv"; my $Yesterday= strftime ("%d-%m-%Y", localtime(time-86400)); my $Current_Date= strftime ("%d-%m-%Y",localtime(time)); print "$Yesterday \n"; print "$Current_Date \n"; open(STDOUT, '>', "/root/Basavaraj/STREAMZ_GCM_APK.txt"); # 创建CSV解析器 my $csv = Text::CSV->new({ sep_char => ',' }); open (my $data, '<:encoding(utf8)', $APK_GCM) or die "Could Not open File '$APK_GCM' $!\n"; open (my $data1,'<:encoding(utf8)', $WEB_GCM) or die "Could Not open File '$WEB_GCM' $!\n"; my %mapA; my $dummyA =<$data>; # 跳过表头 while (my $line = <$data>) { if ($csv->parse($line)) { my @fields = $csv->fields(); my $Brand_Name=$fields[2]; my $GoogleResA=$fields[5]; # 简化初始化:如果键不存在则设为0 $mapA{$Brand_Name}->{Success} //= 0; $mapA{$Brand_Name}->{Failure} //= 0; my $failureA='{error:MismatchSenderId}'; if ($GoogleResA eq $failureA){ $mapA{$Brand_Name}->{Failure}++; print "$Brand_Name: 当前失败计数 $mapA{$Brand_Name}->{Failure} \n"; }else{ $mapA{$Brand_Name}->{Success}++; print "$Brand_Name: 当前成功计数 $mapA{$Brand_Name}->{Success} \n"; } } else { warn "Line could not be parsed: $line\n"; } } print "\n=== 最终统计结果 ===\n"; while (($keyA)=each (%mapA)){ my $success= $mapA{$keyA}->{Success}; my $failure= $mapA{$keyA}->{Failure}; print "$keyA | 成功: $success | 失败: $failure \n"; }
内容的提问来源于stack exchange,提问作者BASAVARAJ JM
相关产品推荐
相关产品推荐

