我有一个学校课程,我刚刚学习哈希,老师学会了阵列的哈希,但并没有真正的哈希,我觉得从长远来看,AoH对我来说会更好。现在我把我的所有数据都放到了单独的变量中,我希望将它们存储到一个AoH中。我在整个时间内都有相同的变量,但值会发生变化。
该程序是一个日志分析器,通过一个巨大的日志文件进行解析,所有数据都是这样的行。
IPADDY x x [DATE:TIME -x] "METHOD URL HTTPVERS" STATUSCODE BYTES "REFERER" "USERAGENT"
示例行
27.112.105.20 - - [09/Oct/2011:07:22:51 -0500] "GET / HTTP/1.1" 200 4886 "-" "Python-urllib/2.4"
现在我得到的所有数据都很好我只是不知道如何填充和阵列哈希,如果有人可以帮助我。
这是一个更新的代码,它抓取数据并尝试将其存储到AoH中。我文件中的输出过去非常完美,就像我现在已经注释掉的印刷品一样。这就是我的输出文件中现在出现的所有“ARRAY(0x2395df0):HASH(0x23d06e8)”。难道我做错了什么?
#!/usr/bin/perl
use strict;
use warnings;
my $j = 0;
my @arrofhash;
my $ipadd;
my $date;
my $time;
my $method;
my $url;
my $httpvers;
my $statuscode;
my $bytes;
my $referer;
my $useragent;
my $dateANDtime;
my ($dummy1, $dummy2, $dummy3);
open ( MYFILE, '>>dodoherty.report');
if ( @ARGV < 1)
{
printf "\n\tUsage: $0 file word(s)\n\n";
exit 0;
}
for (my $i = 0; $i < @ARGV; ++$i)
{
open( HANDLE, $ARGV[$i]);
while( my $line = <HANDLE> )
{
($ipadd, $dummy1, $dummy2, $dateANDtime, $dummy3, $method, $url, $httpvers, $statuscode, $bytes, $referer, $useragent) = split( /\s/, $line);
$method = substr ($method, 1, length($method));
$httpvers = substr ($httpvers, 0, length($httpvers)-1);
$referer = substr ($referer, 1, length($referer)-2);
$useragent = substr ($useragent, 1, length($useragent)-1);
if ( substr ($useragent, length($useragent)-1, length($useragent)) eq '"')
{
chop $useragent;
}
if ( $dateANDtime =~ /\[(\S*)\:(\d{2}\:\d{2}\:\d{2})/)
{
$date = $1;
$time = $2;
}
$arrofhash[$i] = {ipadd => $ipadd, date => $date, 'time' => $time, method => $method, url => $url, httpvers => $httpvers, statuscode => $statuscode, bytes => $bytes, referer => $referer, useragent => $useragent};
# print MYFILE "IPADDY :$ipadd\n";
# print MYFILE "METHOD :$method\n";
# print MYFILE "URL :$url\n";
# print MYFILE "HTTPOVERS : $httpvers\n";
# print MYFILE "STATUS CODE: $statuscode\n";
# print MYFILE "BYTES : $bytes\n";
# print MYFILE "REFERER : $referer\n";
# print MYFILE "USERAGENT : $useragent\n";
# print MYFILE "DATE : $date\n";
# print MYFILE "TIME : $time\n\n";
}
}
for ( my $j = 0; $j < @arrofhash; ++$j)
{
foreach my $hash (@hashkeys)
{
printf MYFILE "%s: %s\n",$hash, $arrofhash[$j];
}
print MYFILE "\n";
}
close (MYFILE);
答案 0 :(得分:1)
基本上你只是声明顶级结构,然后使用它:
my @AoH;
$AoH[0]{some_key} = 5;
$AoH[1]{some_other_key} = 10;
# ^ ^ second level is a hash
# | first level is an array
这将创建一个包含两个元素的数组,每个元素都有一个键,每个元素都有一个键。此功能称为autovivification,它会导致容器结构在使用时弹出。
所有这些都记录在perldsc教程中。
在你的情况下,它会是这样的:
$arrofhash[$i]{key_name} = value;
$arrofhash[$i]{another_key} = another_value;
...
或
$arrofhash[$i] = {key => value, key2 => value2, ...}
一次设置整个哈希。
答案 1 :(得分:1)
常见的初学者错误是不使用变量的词法范围,只是将所有变量声明在顶部,就像你一样。在您需要的范围内声明它们,不多也不少。
在您的情况下,将数据直接存储在散列中,然后将该散列引用推送到数组将是有益的。我也建议不要在这里使用split
,因为它工作不可靠的IMO,你正在拆分引用的字符串,使用虚拟变量去除不需要的数据。而是使用正则表达式。
这个正则表达式不会处理引号内的转义引号,但我觉得你不必处理它,因为你之前使用split来处理它。
您需要为数据添加任何进一步处理,例如提取日期和时间等。如果您想要一些额外的安全性,如果正则表达式似乎已失败,您可以添加警告,例如unless (%f) { warn "Warning: Regex did not match line: '$_'"; next; }
use strict;
use warnings;
use Data::Dumper;
my @all;
while (<DATA>) {
my %f; # make a new hash for each line
# assign the regex captures to a hash slice
@f{qw(ipadd dateANDtime method statuscode bytes referer useragent)} =
/^ # at beginning of line...
(\S+) [\s-]* # capture non-whitespace and ignore whitespace/dash
\[([^]]+)\]\s* # capture what's inside brackets
"([^"]+)"\s* # capture what's inside quotes
(\d+)\s* # capture digits
(\d+)\s*
"([^"]+)"\s*
"([^"]+)"\s*
$/x; # ..until end of line, /x for regex readability only
push @all, \%f; # store hash in array
}
@f{qw(date time)} = split /:/, $f{dateANDtime}, 2;
print Dumper \@all; # show the structure you've captured
__DATA__
27.112.105.20 - - [09/Oct/2011:07:22:51 -0500] "GET / HTTP/1.1" 200 4886 "-" "Python-urllib/2.4"