我有一个Perl程序,它从外部程序解析数据并将其保存到数组中。但是,某些数据未被保存,并在以后尝试检索时返回空白。
这是解析数据的代码,以@packetData
形式出现:
if(@packetData[0] ne ""){
if(!$detectedClient{"@packetData[0]"}) {
my $rawSignal = average(@packetData[2]);
my $distance = 10**((27.55-(20*logten(2437))+abs($rawSignal))/20);
my @newClient = ($rawSignal, # Signal (dBm)
1, # Count
@packetData[0], # Source MAC
time(), # Last seen
$distance); # Distance (m)
$detectedClient{"@packetData[0]"} = [@newClient];
$uniqueClient++;
print "++ New probe request from @packetData[0] [$rawSignal dBm, $distance m]\n";
} else {
$detectedClient{"@packetData[0]"}[1]++;
$detectedClient{"@packetData[0]"}[3] = time();
}
}
print
语句显示信号和距离很好,但尝试从detectedClient
数组显示它,并给出一个空格:
for $key2 ( keys %detectedClient) {
#Signal, Count, MAC, Time
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($detectedClient{$key2}[3]);
my $lastSeen = sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
print STDOUT sprintf("!! %-20s %10s %-20s\n", $detectedClient{$key2}[2], $detectedClient{$key2}[1], $lastSeen, $detectedClient{$key2}[0], $detectedClient{$key2}[4]);
}
为什么会发生这种情况?
答案 0 :(得分:2)
由于您的模式("!! %-20s %10s %-20s\n"
)未引用它们(第4和第5个值),因此不会打印信号和距离。修正:
printf("!! %-20s %5s %-20s %20s %20s\n",
$detectedClient{$key2}[2],
$detectedClient{$key2}[1],
$lastSeen,
$detectedClient{$key2}[0],
$detectedClient{$key2}[4],
);
使用以下方法进行测试:(也必须将for $key2
更改为for my $key2
)
use strict;
use warnings qw( all );
use List::Util qw( sum );
sub average { sum(@{ $_[0] })/@{ $_[0] } }
sub logten { log($_[0])/log(10) }
my @packetData = ("foo", undef, [ 4, 5 ]);
my %detectedClient;
my $uniqueClient;
if(@packetData[0] ne ""){
if(!$detectedClient{"@packetData[0]"}) {
my $rawSignal = average(@packetData[2]);
my $distance = 10**((27.55-(20*logten(2437))+abs($rawSignal))/20);
my @newClient = ($rawSignal, # Signal (dBm)
1, # Count
@packetData[0], # Source MAC
time(), # Last seen
$distance); # Distance (m)
$detectedClient{"@packetData[0]"} = [@newClient];
$uniqueClient++;
print "++ New probe request from @packetData[0] [$rawSignal dBm, $distance m]\n";
} else {
$detectedClient{"@packetData[0]"}[1]++;
$detectedClient{"@packetData[0]"}[3] = time();
}
}
for my $key2 ( keys %detectedClient) {
#Signal, Count, MAC, Time
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($detectedClient{$key2}[3]);
my $lastSeen = sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
printf("!! %-20s %5s %-20s %20s %20s\n",
$detectedClient{$key2}[2],
$detectedClient{$key2}[1],
$lastSeen, $detectedClient{$key2}[0],
$detectedClient{$key2}[4],
);
}
输出:
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 18.
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 19.
Scalar value @packetData[2] better written as $packetData[2] at a.pl line 20.
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 24.
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 27.
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 29.
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 31.
Scalar value @packetData[0] better written as $packetData[0] at a.pl line 32.
++ New probe request from foo [4.5 dBm, 0.0164302613184467 m]
!! foo 1 2016/05/16 15:19:38 4.5 0.0164302613184467
下次,请提供一个最小的,可运行的问题演示。
答案 1 :(得分:-3)
整个数组的语法是@array
但是要访问单个元素,它是(例如)$array[0]
此外,还有一种更好的方法可以在您的上下文中编写内部if
。
第三,您正在使用detectedClient
的数组引用,因此语法可以从$detectedClient{$smac}[1]++
更改为$detectedClient{$smac}->[1]++
,这样可以更加清晰。我已在下面的代码中更改了它,您也可以在打印时更改它。
这是您的代码经过修改以反映所有内容并缩短为使用标量:
my $smac = $packetData[0];
if ($smac ne "") {
if(! ref($detectedClient{$smac})) {
my $rawSignal = average($packetData[2]);
my $distance = 10**((27.55-(20*logten(2437))+abs($rawSignal))/20);
my @newClient = ($rawSignal, # Signal (dBm)
1, # Count
$smac, # Source MAC
time(), # Last seen
$distance); # Distance (m)
$detectedClient{$smac} = [@newClient];
$uniqueClient++;
print "++ New probe request from $smac [$rawSignal dBm, $distance m]\n";
} else {
my $ptr = $detectedClient{$smac};
$ptr->[1]++;
$ptr->[3] = time();
}
}
<强>更新强>
使用标量和一点重新编写,打印代码如下:
for $key2 ( keys %detectedClient) {
my $ptr = $detectedClient{$key2};
#Signal, Count, MAC, Time
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime($ptr->[3]);
my $lastSeen = sprintf("%04d/%02d/%02d %02d:%02d:%02d",
$year+1900, $mon+1, $mday, $hour, $min, $sec);
print STDOUT sprintf("!! %-20s %10s %-20s\n",
$ptr->[2], $ptr->[1],
$lastSeen, $ptr->[0], $ptr->[4]);
}
现在,更容易看到[对我来说,至少;-)]格式是两个字段缩短[所以最后两个参数不会被打印]。
所以,改为:
printf("!! %-20s %10s %-20s %10s %10s\n",