Perl数组不保存所有变量

时间:2016-05-16 16:55:55

标签: arrays 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 个答案:

答案 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",