2016-05-16 37 views
-1

我有一個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

回答

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 $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 

下一次,請提供一個最小的,可運行的問題演示。

-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(); 
    } 
} 

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通過省略下標之間的箭頭而造成語法錯誤。他沒有。這不是任何錯誤。 –