Хранение данных в массив хэшей - PullRequest
1 голос
/ 29 февраля 2012

У меня есть школьная программа, которую я только что получил, и мы изучаем хэши, и учитель просмотрел хэши массивов, но на самом деле их не было, и я чувствую, что 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);

Ответы [ 2 ]

1 голос
/ 29 февраля 2012

Распространенная ошибка новичка - не использовать лексическую область видимости переменных, а просто объявить все переменные вверху, как вы. Объявите их в том объеме, в котором они вам нужны, не больше, не меньше.

В вашем случае было бы полезно просто сохранить данные непосредственно в хэше, а затем вставить эту ссылку в массив. Я также не рекомендовал бы использовать split здесь, поскольку он работает ненадежно IMO, а вы разбиваете строки в кавычках, используя фиктивные переменные, чтобы избавиться от нежелательных данных. Вместо этого используйте регулярное выражение.

Это регулярное выражение не будет обрабатывать экранированные кавычки внутри кавычек, но я чувствую, что вам не придется иметь с этим дело, так как вы использовали сплит ранее для обработки этого.

Вам необходимо будет добавить любую дополнительную обработку к данным, такую ​​как извлечение даты и времени и т. Д. Если вы хотите добавить дополнительную безопасность, вы можете добавить предупреждение, если регулярное выражение, похоже, не удалось, например, 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"
1 голос
/ 29 февраля 2012

По сути, вы просто объявляете структуру верхнего уровня, а затем используете ее:

my @AoH;

$AoH[0]{some_key} = 5;
$AoH[1]{some_other_key} = 10;
#    ^  ^ second level is a hash
#    | first level is an array

Который создал бы массив с двумя элементами, каждый из которых хэширует каждый с одним ключом Эта функция называется автовивификацией, и она вызывает появление контейнерных структур при их использовании.

Все это описано в руководстве perldsc .

В вашем случае это будет что-то вроде:

$arrofhash[$i]{key_name} = value;
$arrofhash[$i]{another_key} = another_value;
...

или

$arrofhash[$i] = {key => value, key2 => value2, ...}

для установки всего хэша за один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...