Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> посчитать количество уникальных эллементов массива 
:(
    Опции темы
box
Дата 20.1.2010, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 506
Регистрация: 27.2.2007

Репутация: нет
Всего: 0



всем привет !
пишу парсер логов .
вообщем нужно посчитать кол-во одинаковых вхождений массива .
я пытаюсь так :
Код

#!/usr/bin/perl 
use strict;

my @dot=();
my %res=();
open(logfile, 'access.log');
while($arr=<logfile>){
($ip_temp,$host_temp,$string_temp)=split(/\|/, $arr);

@dot=$ip_temp;
#print $ip_temp.":".$host_temp.":".$string_temp."\n";
}

grep { $res{ $_ }++ } (@dot);
foreach ( sort { $a <=> $b } keys %res )
{
          print "$_ - $res{ $_ } elem.\n";
}


но перл ругается . где ощибка ? 
PM MAIL   Вверх
Egik2
Дата 20.1.2010, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 302
Регистрация: 29.7.2008
Где: Агудзера

Репутация: 1
Всего: 11



Как ругается то?

Добавлено @ 21:13
Аа, протестил у себя, убери use strict, либо объяви переменные перед их использованием, а именно $ip_temp,$host_temp,$string_temp, $arr.
Например так:
Код

#!/usr/bin/perl 
use strict;
my @dot=();
my %res=();
open(logfile, 'access.log');
while(my $arr=<logfile>){
my ($ip_temp,$host_temp,$string_temp)=split(/\|/, $arr);
@dot=$ip_temp;
#print $ip_temp.":".$host_temp.":".$string_temp."\n";
}
grep { $res{ $_ }++ } (@dot);
foreach ( sort { $a <=> $b } keys %res )
{
          print "$_ - $res{ $_ } elem.\n";
}


Это сообщение отредактировал(а) Egik2 - 20.1.2010, 21:15


--------------------
Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall)
a-nav.com
developer-blog.ru
world-poetry.org
PM MAIL WWW ICQ   Вверх
arto
Дата 20.1.2010, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



работать не будет
PM MAIL ICQ   Вверх
box
Дата 20.1.2010, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 506
Регистрация: 27.2.2007

Репутация: нет
Всего: 0



да , не работает .
и подскажите как выполнить все вышеперечисленное по отношению к трех мерному массиву с ключем $ip_temp
PM MAIL   Вверх
Egik2
Дата 20.1.2010, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 302
Регистрация: 29.7.2008
Где: Агудзера

Репутация: 1
Всего: 11



Можешь с самого начала сформулировать задачу, что именно тебе нужно?

Добавлено через 10 минут и 47 секунд
Если я правильно понял, то надо следующее:
посчитать сколько строк в файле для каждого $ip_temp.
Если так, то попробуй это:
Код

use strict;
open(LOG, "access.log") or die "Can't open log $!";
my %hash = ();
while(<LOG>){
    my ($ip_temp, $host_temp, $string_temp) = split(/\|/, $_);
        $hash{$ip_temp}++;
}
foreach my $k (keys %hash) {
    print "$k - $hash{$k}\n";
}



--------------------
Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall)
a-nav.com
developer-blog.ru
world-poetry.org
PM MAIL WWW ICQ   Вверх
box
Дата 20.1.2010, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 506
Регистрация: 27.2.2007

Репутация: нет
Всего: 0



есть лог такого формата :
ip|host|string
где :
ip-ип адрес
host-имя хоста
string-строка запроса

пример строки :
188.36.83.194|example.com|GET /shop/images/items/Astral_rental.gif HTTP/1.1

так вот надо посчитать сколько уникальных значений ip и загнать все данные в массив типа 
$array('кол-во уникальных  значений 1 ого ip', 'ip', 'host', 'string'); и так дале.....

на awk это будет выглядеть так :
Код

awk '(req[$1]++)' access.log | awk '{
print $1, $2, $3
}' | sort | uniq -c | sort -r -n | head -n  100




Это сообщение отредактировал(а) box - 20.1.2010, 23:07
PM MAIL   Вверх
amg
Дата 21.1.2010, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Для начала:
Код
die "Usage $0 access.log\n" unless @ARGV;

while (<>) {
  m/\|/ && push @{$h{$`}}, $';
}

foreach (sort {@{$h{$b}}<=>@{$h{$a}}} keys %h) {
  print scalar @{$h{$_}}, "  $_\n @{$h{$_}}";
}


PM MAIL   Вверх
Egik2
Дата 21.1.2010, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 302
Регистрация: 29.7.2008
Где: Агудзера

Репутация: 1
Всего: 11



То есть допустим, у тебя следующие записи в логе:
188.36.83.194|example.com|GET /shop/images/items/Astral_rental.gif HTTP/1.1
188.36.83.194|example111.com|GET /shop/images/items/Astral_rental.gif HTTP/1.1
188.36.83.194|example222.com|GET /shop/images/items/Astral_rental.gif HTTP/1.1
188.36.83.194|example111.com|GET /shop/images/items/Astral_rental.gif HTTP/1.1
Как должен выглядеть массив?



--------------------
Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall)
a-nav.com
developer-blog.ru
world-poetry.org
PM MAIL WWW ICQ   Вверх
box
Дата 21.1.2010, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 506
Регистрация: 27.2.2007

Репутация: нет
Всего: 0



Так:
Код

array(4=> array("ip" =>"188.36.83.194", "host" => array(1 => "example.com", 2 => "example1111.com", 3 => "example2222.com"),  "string" => "GET /shop/images/items/Astral_rental.gif HTTP/1.1"));

Важно знать кол-во обращений из данного ип , строку и хост.
И все данные должны быть уникальные , никаких повторений быть не должно .

Это сообщение отредактировал(а) box - 21.1.2010, 19:52
PM MAIL   Вверх
Egik2
Дата 21.1.2010, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 302
Регистрация: 29.7.2008
Где: Агудзера

Репутация: 1
Всего: 11



Повторяться не должны целые строки?
Я не совсем понял твою структуру данных. 
Наверное для строк тоже должен быть массив?
Может так хочешь:
%hash = (
   "188.36.83.194" => 
        [
            "4", //число повторений ip
            "example.com" => [  "1", //число повторений host
                                              [
                                                 "1", //число повторений строк для данного host
                                                 "GET /shop/images/items/Astral_rental.gif HTTP/1.1"
                                              ]
                                            
                                        ],
             "example111.com" => [ "2", 
                                                          [
                                                              "1", 
                                                              "GET /shop/images/items/Astral_rental.gif HTTP/1.1"
                                                          ]
                                        ],
              "example222.com" => [  "1",
                                                          [
                                                              "1", 
                                                              "GET /shop/images/items/Astral_rental.gif HTTP/1.1"
                                                          ]
                                        ]
        ]
)

Выглядит ужасно, и если большой лог, строиться будет долго.




--------------------
Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall)
a-nav.com
developer-blog.ru
world-poetry.org
PM MAIL WWW ICQ   Вверх
ramus
Дата 22.1.2010, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 21.2.2008

Репутация: 1
Всего: 1



Когда речь идет об уникальности, то эффективнее на перл использовать хеш, а не массив. 
Например логика такая:
читаем лог построчно
разбираем строку: IP в $ip, хост в $host, строку в $str
$key=$ip;
смотрим есть ли уже такой элемент хеша (if defined($hash_ip{$key})
если есть, то $hash_ip{$key}++
иначе инициализируем $hash_ip{$key}=1
запоминаем в других хешах то, что надо (в качестве ключа ip)
$hash_str{$key}=$str
$hash_host{$key}=$host
конец цикла чтения лога

далее необходимая обработка с сортировками
например сортировка по ip
foreach my $ip1 (sort keys %hash_ip) {
...
  print $hash_host{$ip1};
...
}

Недостатки этого алгоритма:
- если лог большой (по опыту более 300МБ) то потребуется много оперативной памяти
- если с одного IP будут разные строки, то в ключ хеша потребуется вводить эту строку для сохранения уникальности



PM MAIL   Вверх
box
Дата 22.1.2010, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 506
Регистрация: 27.2.2007

Репутация: нет
Всего: 0



а если я помещу в хеш все данные так:

Код


    my ($ip_temp, $host_temp, $string_temp) = split(/\|/, $_);
        $hash{$host_temp."|".$ip_temp."|".$string_temp}++;


 
и птом буду обрабатывать так :

Код

foreach my $k (keys %hash) {
....................
}


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

Это сообщение отредактировал(а) box - 22.1.2010, 01:03
PM MAIL   Вверх
shamber
Дата 22.1.2010, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1422
Регистрация: 5.9.2006
Где: Россия

Репутация: 17
Всего: 18



box, вы можете рассчитывать, но  память здесь будет слабое место

Добавлено через 2 минуты и 5 секунд
зачем вам split, если исходная строка и то чтчо вы потом загоняете в хеш это одно и тоже?
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0550 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.