检查元素是否处于哈希状态?

时间:2014-04-16 16:26:17

标签: arrays perl hash

好的,我有以下哈希,并尝试匹配引用的元素:

$VAR1 = {
          '743' => '00:1',
          '20687' => '01:3',
};

有人可以告诉我如何检查值'00:1'(作为示例)是否与另一个变量匹配?这就是我目前所拥有的并且不起作用:

if($pids{$pid} == qr/$time/){
    $pids{$pid}{$time}[$y] = $line;
    $y++;
};

我也试过了if(exists($pids{$pid}{$time}))和其他一些人。

更新

与下面的问题有关,pids是一个哈希值,%pids。

当我运行哈希表而不匹配$ time时,这就是哈希表的出现,这正是我想要的:

$VAR1 = {
          '743' => '00:1',
          '4771' => {
                      '23:5' => [
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: USER test
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: PASS password
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: FTP LOGIN FROM 192.168.0.2 [192.168.0.2], test
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: CWD /home/test/
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: TYPE Image
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: PASV
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: RETR test
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: QUIT
',
                                  'Dec  1 23:59:23 ftp1 ftpd[4771]: FTP session closed
'
                                ]
                    },

以下是将要通过的数据示例:

Dec  1 23:59:03 ftp1 ftpd[4771]: USER test
Dec  1 23:59:03 ftp1 ftpd[4771]: PASS password  
Dec  1 23:59:03 ftp1 ftpd[4771]: FTP LOGIN FROM 192.168.0.02 [192.168.0.2], test  
Dec  1 15:02:03 ftp1 ftpd[4771]: CWD /home/test  # Looks same but different time so not a match  
Dec  1 23:59:03 ftp1 ftpd[4771]: CWD /home/test  
Dec  1 23:59:03 ftp1 ftpd[4771]: TYPE Image

正如你可以看到的那样,我可以有两条不同的“pids”,我只想匹配那些时间,而不是两者。

如果您需要更多相关信息,我会在另一个问题中提供所有详细信息,但我似乎已经死在水中: Playing with Hashes from a FTP flow in Perl

1 个答案:

答案 0 :(得分:1)

如果您可以从每一行中提取$time,这很容易:

use strict;
use warnings;
use Data::Dump;

my %pids;

while (my $line = <>) {
    chomp $line;
    my ($time, $pid) = $line =~ /([0-9]{1,2}:[0-9]) .*? \[([0-9]+)\] /x or next;
    push @{ $pids{$pid}{$time} }, $line;
}

dd \%pids;

__DATA__
Dec  1 23:59:03 ftp1 ftpd[4771]: USER test
Dec  1 23:59:03 ftp1 ftpd[4771]: PASS password  
Dec  1 23:59:03 ftp1 ftpd[4771]: FTP LOGIN FROM 192.168.0.02 [192.168.0.2], test  
Dec  1 15:02:03 ftp1 ftpd[4771]: CWD /home/test  # Looks same but different time so not a match  
Dec  1 23:59:03 ftp1 ftpd[4771]: CWD /home/test  
Dec  1 23:59:03 ftp1 ftpd[4771]: TYPE Image
Dec  2 23:12:03 ftp1 ftpd[1234]: USER test
Dec  2 23:12:03 ftp1 ftpd[1234]: PASS password  
Dec  2 23:12:03 ftp1 ftpd[1234]: CWD /home/test 

会产生以下输出:

{
  1234 => {
            "23:1" => [
              "Dec  2 23:12:03 ftp1 ftpd[1234]: USER test",
              "Dec  2 23:12:03 ftp1 ftpd[1234]: PASS password  ",
              "Dec  2 23:12:03 ftp1 ftpd[1234]: CWD /home/test ",
            ],
          },
  4771 => {
            "15:0" => [
                        "Dec  1 15:02:03 ftp1 ftpd[4771]: CWD /home/test  # Looks same but different time so not a match  ",
                      ],
            "23:5" => [
                        "Dec  1 23:59:03 ftp1 ftpd[4771]: USER test",
                        "Dec  1 23:59:03 ftp1 ftpd[4771]: PASS password  ",
                        "Dec  1 23:59:03 ftp1 ftpd[4771]: FTP LOGIN FROM 192.168.0.02 [192.168.0.2], test  ",
                        "Dec  1 23:59:03 ftp1 ftpd[4771]: CWD /home/test  ",
                        "Dec  1 23:59:03 ftp1 ftpd[4771]: TYPE Image",
                      ],
          },
}

如果您只对预定义的PID和时间集感兴趣,您可以执行以下操作:

my %pids = (
    5678 => { '00:1' => [] },
    4771 => { '23:5' => [] },
);

while (my $line = <>) {
    chomp $line;
    my ($time, $pid) = $line =~ /([0-9]{1,2}:[0-9]) .*? \[([0-9]+)\] /x or next;
    if (exists $pids{$pid} and exists $pids{$pids}{$time}) {
        push @{ $pids{$pid}{$time} }, $line;
    }
}

my %times;
@times{qw/ 00:01 23:5 /} = ();

...

    push @{ $pids{$pid}{$time} }, $line if exists $times{$time};

如果无法以一般方式从线上提取时间,您可以匹配所有可能的时间:

my %pids = (
    5678 => { '00:1' => [] },
    4771 => { '23:5' => [] },
);

while (my $line = <>) {
    chomp $line;
    my ($pid) = $line =~ /\[([0-9]+)\]/ or next;
    next if not exists $pids{$pid};
    my $time_regex = join '|', map quotemeta, keys %{ $pids{$pid} };
    my ($time) = $line =~ /($time_regex)/ or next;
    push @{ $pids{$pid}{$time} }, $line;
}