2012-02-29 2 views
1

У меня есть школьная программа, которую я только что получил, и мы изучаем хеши, и учитель перешел хэши массивов, но не очень много хешей, и я чувствую, что AoH будет работать лучше для меня в долгосрочной перспективе. Прямо сейчас я получаю все свои данные в отдельные переменные, и я хочу сохранить их в AoH bc. У меня одинаковые переменные за все время, но значения меняются.Хранение данных в массиве хешей

Что такое программа, является анализатором журнала и анализирует через гигантский файл журнала, и все данные являются линиями, которые выглядят так.

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); 

ответ

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" 
+0

Ничего себе это выглядит намного чище, только моя мысль: у меня есть дата и время как отдельные переменные, хотя я уверен, что могу немного исправить это регулярное выражение. – Trance339

+1

@ Trance339 Я бы посоветовал вам после этого обработать. Например. 'my ($ date, $ time) = split /: /, $ f {dateANDtime}, 2;' «2» - это аргумент LIMIT для разделения, который определяет, сколько полей должно быть возвращено. – TLP

1

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

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, ...} 

установить весь хэш сразу.

+0

Я думаю, что я собираюсь попробовать весь комплект сразу в своем заявлении и посмотреть, где это меня принимает. Похоже, я мог бы просто сделать что-то вроде ... $ arrofhash [$ i] = {ipadd => $ ipadd, date => $ date, time => $ time ...} и так далее с чем-то подобным, поэтому каждый раз ключ тот же, но значение равно другой. – Trance339

Смежные вопросы