Процесс «прочиталзапомнил»
Процесс «прочитал-запомнил»
Крайность, противоположная предыдущему подходу (там мы «пробегали» по данным как можно быстрее), заключается в чтении их в память и последующей обработке после чтения. Рассмотрим несколько версий этой стратегии.
Для начала приведем простой пример: скажем, у нас есть журнал FTP-сервера и требуется узнать, какие файлы скачивались чаще других. Вот несколько строк из журнала FTP-сервера wu-ftpd:
Sun Dec 27 05:18:57 1998 1 nic.funet.fi 11868 /net/ftp.funet.fi/CPAN/
MIRRORING.FROM a _ о a cpan@perl.org ftp 0 *
Sun Dec 27 05:52:28 1998 25 kju.hc.congress.ccc.de 269273 /CPAN/doc/FAQs/FAQ/
PerlFAQ.html a _ о a mozilla@ ftp 0 *
Sun Dec 27 06:15:04 1998 1 rising-sun.media.mit.edu 11868 /CPAN/
MIRRORING. FROM b __ о a root@rising-sun. media, mit. edu ftp 0 *
Sun Dec 27 06:15:05 1998 1 rising-sun.media.mit.edu 35993 /CPAN/RECENT.html b
о а root@rising-sun.media.mit.edu ftp 0
А вот список полей, из которых состоят приведенные выше строки (все подробности о каждом поле ищите в страницах руководств xferlog(B) сервера wu-ftpd).
Номер поля | Имя поля |
0 | current-time (текущее время) |
1 | transfer-time (время передачи, в секундах) |
2 | remote-host (удаленный узел) |
3 | filesize (размер файла) |
4 | filename (имя файла) |
5 | transfer-type (тип передачи) |
6 | special-action-flag (специальный флаг) |
7 | direction (направление) |
8 | access-mode (режим доступа) |
9 | use r name (имя пользователя) |
10 | service-name (имя службы) |
11 | authentication-method (меод аутентификации) |
12 | authenticated-user-id (идентификатор аутентифицированного пользователя) |
Вот пример программы, сообщающей о том, какие файлы передавались чаще других:
Sxferlog = "/var/adin/Iog/xferlog";
open(XFERLOG,Sxferlog) or die "Невозможно открыть Sxferlog•$!\n":
while (<XFERLOG>){
$files{(sDlit)[8]}++ }
close(XFERLOG);
for (sort {$files{$b} <=> $files{$a}||$a cmp $b} keys %files){
print "$_:$files{$_}\n"; >
Мы считываем каждую строку файла, используя имя файла в качестве ключа кэша, и увеличиваем значение для этого ключа. Имя файла выделяется из каждой строки журнала при помощи индекса массива, ссылающегося на определенный элемент списка, возвращенного функцией split():
$files{(split)[8]>++;
Вы могли заметить, что элемент, на который мы ссылаемся (8), отличается от 8-го поля из списка полей xferlog, приведенного выше. Это печальные последствия того, что в оригинальном файле отсутствуют разделители полей. Мы разбиваем строки из журнала по пробелам (что является значением по умолчанию для split()), так что дата разбивается на пять отдельных элементов списка.
В этом примере применяется искусный прием - сортировку значений выполняет анонимная функция sort:
for (sort {$files{$b} <=> $files{$a}||$a cmp $b} keys %files){
Обратите внимание, что переменные $а и $b в первой части расположены не в алфавитном порядке. Это приводит к тому, что sort выводит элементы в обратном порядке, т. е. первыми отображаются самые «популярные» файлы. Вторая часть анонимной функции sort ( I $a cmp $о) гарантирует, что файлы с одинаковой популярностью будут перечислены в отсортированном порядке.
Для того чтобы этот сценарий подсчитывал только некоторые файлы и каталоги, можно задать регулярное выражение в качестве первого аргумента для сценария. Например, если добавить
next unless /$ARGV[0]/o;
в цикл while(), можно будет задавать регулярные выражения для ограничения учитываемых файлов. Давайте посмотрим на другой пример подхода «прочитал-запомнил», в котором используется программа «поиска брешей» из предыдущего раздела. В предыдущем примере выводилась информация только об успешной регистрации с сайтов злоумышленника. Узнать о неудавшихся попытках мы не можем. Чтобы получить такую информацию, мы рассмотрим другой файл журнала.