2016-05-16 13 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

信号との距離が印刷されません。修正:

次使用してテスト
printf("!! %-20s %5s %-20s %20s %20s\n", 
    $detectedClient{$key2}[2], 
    $detectedClient{$key2}[1], 
    $lastSeen, 
    $detectedClient{$key2}[0], 
    $detectedClient{$key2}[4], 
); 

:(あまりにfor my $key2for $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であるが、個々の要素にアクセスするために、それはまた、あなたのコンテキストで内部ifを書き込むためのより良い方法がある(例えば)$array[0]

あります。

第3に、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]); 
} 

今、 [少なくとも私にとっては、;-)]書式が2つのフィールドだけ短いことが分かりやすいので[最後の2つの引数は表示されません]。

ので、代わりにこのような何か:あなたのパターン("!! %-20s %10s %-20s\n"は)彼ら(4番目と5番目の値)を参照していないため

printf("!! %-20s %10s %-20s %10s %10s\n", 
+3

'$ foo { bar] [1] 'は' $ foo {bar} - > [1] 'とまったく同じです。角かっこの間の矢印は必須ではありません。読んでください:http://perldoc.perl.org/perlreftut.html#Arrow-Rule –

+0

@PaulL私は誤って以前のバージョンをプッシュしていました。ここではそれらが必要です。また、構文は意図的にはっきりしていますが、IMO [と私はPerlを20+用に書いていて、そのうちの25万行を持っています] –

+2

コードに加えて、変更する必要があるのはあなたの答えです。あなたは、OPが下付き文字間の矢印を省略することによって構文上の誤りを起こしたと主張しています。彼はしませんでした。それはどんな種類の誤りでもありません。 –

関連する問題