Добрый день.Не так давно начал изучать Perl (2 недели), до этого кроме #!/bin/sh ни на чем не программировал.
Поставил себе такую задачку - написать скрипт на Perl-е, который из журнала maillog (почтовый сервер Postfix 2.2.8) выбирает следующие данные: Месяц, число, время, ip-адрес отправителя, поля from и to и размер письма.
Все хорошо, но на некоторых письмах происходит затык - некоторые строки не разбиваются функцией split на элементы - бьюсь второй день, но причину не вижу.
Вот сама программа:
#!/usr/local/bin/perl
# Открыли файл, загнали все в массив @a
open(MAIL, "/home/admin/perl/maillog.0");
@a=<MAIL>;
close(MAIL);$j=0;
for ($i=0;$i<$#a+1;$i++) {
$#b=0;
@b=split(/\s+/,$a[$i]); # Строку дробим на элементы
if (($b[6] =~ m/client=(.+)/) and ($b[6] ne 'client=localhost.domen.ru[127.0.0.1]'))
{
$c1[$j]=$b[5]; # получаем массив @c1, содержащий Message-ID писем, поступивших на обработку
$j++;
}
}$j=0;
for ($i=0;$i<$#a+1;$i++) {
$#b=0;
@b=split(/\s+/,$a[$i]);
if ($b[6] eq 'removed')
{
$c2[$j]=$b[5]; # получили массив @c2, содержащий Message-ID писем, успешно обработанных и удаленных из очереди задач
$j++;
}
}$k=0;
for ($i=0;$i<$#c1+1;$i++)
{ for ($j=0;$j<$#c2+1;$j++) {
if ($c1[$i] eq $c2[$j]) { $c[$k]=$c1[$i]; $k++; }}}
# Получили массив @c, содержащий пересечение массивов @c1 и @c2$j=0;
for ($i=0;$i<$#a+1;$i++) {
$#b=0;
@b=split(/\s+/,$a[$i]);
if (($b[6] =~ m/client=(.+)/) and ($b[6] ne 'client=localhost.domen.ru[127.0.0.1]') and ($b[5] eq $c[$j]))
{
$d[$j]=$b[0]."\t".$b[1]."\t".$b[2]."\t";
$b[6] =~ s/client=(.+)\[(.+)\]/$2/g;
$d[$j].=$b[6].="\t\t";
$j++;
}
}# Формируем массив @d, который будем заполнять нужными данными.
# До этого момента все работает нормально, а вот с полями from, to и size - беда - на некоторых строках не работает функция split.$j=0;
for ($i=0;$i<$#a+1;$i++) {
$#b=0;
@b=split(/\s+/,$a[$i]);
if (($b[5] eq $c[$j]) and ($b[7] =~ m/size=(.+?),/))
{
$b[7] =~ s/size=(.+?),/$1/g;
$d[$j] .= $b[7];
$d[$j] .= "\t";
$j++;
}
}Привожу кусок maillog-а, именно в этом месте скрипт затыкается:
Apr 6 02:10:33 newgateway postfix/smtpd[63214]: 61F8561C0E: client=unknown[68.56.22.107]
Apr 6 02:10:35 newgateway postfix/cleanup[63215]: 61F8561C0E: message-id=<20060405201033.61F8561C0E@newgateway.domen.ru>
Apr 6 02:10:35 newgateway postfix/qmgr[70203]: 61F8561C0E: from=<bj21@com2com.ru>, size=1335, nrcpt=1 (queue active)
Apr 6 02:10:36 newgateway postfix/lmtp[63170]: 61F8561C0E: to=<egor@domen.ru>, relay=127.0.0.1[127.0.0.1], delay=4, status=sent (250 2.0.0 Ok (2.0.0 <igor@domen.ru> OK ))
Apr 6 02:10:36 newgateway postfix/qmgr[70203]: 61F8561C0E: removed
В чем была проблема понял смутно (то есть не понял), но задачку решил полным перебором:#!/usr/local/bin/perl
open(MAIL, "/home/admin/perl/maillog.0");
@a=<MAIL>;
close(MAIL);$j=0;
for ($i=0;$i<$#a+1;$i++) {
$#b=0;
@b=split(/\s+/,$a[$i]);
if (($b[6] =~ m/client=(.+)/) and ($b[6] ne 'client=localhost.domen.ru[127.0.0.1]'))
{
$c1[$j]=$b[5];
$j++;
}
}$j=0;
for ($i=0;$i<$#a+1;$i++) {
$#b=0;
@b=split(/\s+/,$a[$i]);
if ($b[6] eq 'removed')
{
$c2[$j]=$b[5];
$j++;
}
}
$k=0;
for ($i=0;$i<$#c1+1;$i++)
{ for ($j=0;$j<$#c2+1;$j++) {
if ($c1[$i] eq $c2[$j]) { $c[$k]=$c1[$i]; $k++; }}}for ($j=0;$j<$#c+1;$j++)
{ for ($i=0;$i<$#a+1;$i++)
{
$#b=0;
@b=split(/\s+/,$a[$i]);
if ($c[$j] eq $b[5])
{
if (($b[6] =~ m/client=(.+)/) and ($b[6] ne 'client=localhost.domen.ru[127.0.0.1]'))
{
$d[$j]=$b[0]." ".$b[1]." ".$b[2]." ";
$b[6] =~ s/client=(.+)\[(.+)\]/$2/g;
$d[$j].=$b[6].=" ";
}
if ($b[6] =~ m/from=<(.+)>,/)
{
$b[6] =~ s/from=<(.+)>,/$1/g;
$d[$j] .= $b[6];
$d[$j] .= " ";
}
if ($b[7] =~ m/size=(.+),/)
{
$b[7] =~ s/size=(.+),/$1/g;
$d[$j] .= $b[7];
$d[$j] .= " ";
}
if ($b[6] =~ m/to=<(.+)>,/)
{
$b[6] =~ s/to=<(.+)>,/$1/g;
$d[$j] .= $b[6];
}
}
print $d[$j], "\n";
}Но этот скрипт работает слишком медленно.
Укажите пожалуйста пути к увеличению скорости работы (кроме замены железа, конечно) :)
>Но этот скрипт работает слишком медленно.
>Укажите пожалуйста пути к увеличению скорости работы (кроме замены железа, конечно) :)Открыть, наконец, для себя проект mailgraph.
Спасибо за совет, но у меня другая цель.Готовое решение мне не нужно.
>Спасибо за совет, но у меня другая цель.
>
>Готовое решение мне не нужно.Взять готовое, разобраться в нем и создать своё. Проявите ф0нтазию. Или Вы предлагаете, чтобы Вам разжевали на форуме проект mailgraph и Вы потом создали своё решение?
Вы меня не поняли - я изучаю Perl, взялся написать программу - как задачку. Написал. Задачу решил. Теперь интересуюсь мнением профессиональных программистов на Perl - с помощью каких методов можно улучшить программу.И проект mailgraph тут совершенно не причем!!!
ну, в общем, я бы сделал примерно так. Занося в хэш отдельные поля по мере поступления инфы, а потом вывести все разом.
Правда, возможны всякие варнинги и тому подобное - это просто руководство к действию :)
--------- тута началоopen(MAIL, "mail.log") or die "$!";
%result = ();
while ( <MAIL> ) {
($time,$id) = /^(\w+\s+\d+\s+[0-9:]+)\s+.+?:\s+(\w{10}):/ or next; # не сработало, значит, что-то вроде warning
$result{$id}{time} = $time;
# далее заносим значения полей, которые есть в строке, в хэш
/client=\[(.+?)\]/ and $result{$id}{ip} = $1;
/from=<(.+?)>/ and $result{$id}{from} = $1;
/to=<(.+?)>/ and $result{$id}{to} = $1;
/size=(\d+?),/ and $result{$id}{size} = $1;
}close(MAIL);
# теперь можно вывести то, что мы насобирали. Правда, без всякой сортировки
print "$_->{time} $_->{ip} $_->{from} $_->{to} $_->{size}\n" foreach (%result);--------- тута конец
>Вы меня не поняли - я изучаю Perl, взялся написать программу -
>как задачку. Написал. Задачу решил.А эту строчку Вы в features к программе запишите?!:
"Привожу кусок maillog-а, именно в этом месте скрипт затыкается"
>Теперь интересуюсь мнением профессиональных программистов на
>Perl - с помощью каких методов можно улучшить программу.www.google.com /log analize perl