Perl数组不保存所有变量

问题描述:

我有一个Perl程序,它解析外部程序中的数据并将其保存到数组中。但是,有些数据未保存,稍后尝试恢复时会返回空白。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]); 
} 

任何想法为什么会发生这种情况?

+2

总是使用'​​use strict;使用警告qw(全部);'! – ikegami

+0

我有两个在脚本的顶部,但为了清晰而忽略它们(以及其余的脚本) – CyberJacob

+5

@Cyber​​Jacob:如果你有'使用警告',那么你忽略了'Scalar value @packetData [ 0]更好地写为$ packetData [0]'。你为什么这样做? – Borodin

信号和距离不打印,因为你的模式("!! %-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 $key2for 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 

下一次,请提供一个最小的,可运行的问题演示。

用于整个阵列的语法是@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(); 
    } 
} 

UPDATE:

应用使用标量和一点重新缩进时,打印代码如下:

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", 
+3

'$ foo { bar] [1]'与$ foo {bar} - > [1]'完全相同。括号/括号之间的箭头不是必需的。请阅读:http://perldoc.perl.org/perlreftut.html#Arrow-Rule –

+0

@PaulL我误推了一个早期版本。这里,它们是必需的。另外,对于intent来说语法更清晰,[[我已经写了perl for 20+,并且有大约250,000行] –

+2

除了代码之外,这是您需要更改的答案。您声称OP通过省略下标之间的箭头而造成语法错误。他没有。这不是任何错误。 –