Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Как разобрать данные в файле?


Автор: witos 22.3.2006, 14:14
помогите чайнику, который только начал разбираться с perl...

Есть лог-файл следующего вида:

Sun Mar 19 23:18:54 YEKT 2006 ppp3 10.6.20.250 LOGIN
Sun Mar 19 23:32:27 YEKT 2006 ppp3 10.6.20.250 LOGOUT
Mon Mar 20 19:49:45 YEKT 2006 ppp3 10.6.20.250 LOGIN
Mon Mar 20 20:28:25 YEKT 2006 ppp3 10.6.20.250 LOGOUT
Tue Mar 21 20:52:02 YEKT 2006 ppp3 10.6.20.250 LOGIN
Tue Mar 21 20:52:06 YEKT 2006 ppp3 10.6.20.250 LOGOUT
Tue Mar 21 20:52:25 YEKT 2006 ppp3 10.6.20.250 LOGIN
Tue Mar 21 20:54:05 YEKT 2006 ppp5 10.6.20.240 LOGIN
Tue Mar 21 20:56:01 YEKT 2006 ppp5 10.6.20.240 LOGOUT
Tue Mar 21 20:56:33 YEKT 2006 ppp3 10.6.20.250 LOGOUT
Tue Mar 21 20:58:46 YEKT 2006 ppp3 10.6.20.250 LOGIN
Tue Mar 21 21:37:17 YEKT 2006 ppp3 10.6.20.250 LOGOUT

нужно занести данные в файл, чтоб строки выглядели так - " IP-адрес pppX login_date_time logout_date_time", т.е.
как сделать из 2-х записей в исходном лог-файле (вход и выход) одну в другом файле со временем и входа, и выхода?
( т.е. чтоб получить записи вида:
10.6.20.250 ppp3 19.03.2006 23:18:54 19.03.2006 23:32:27
10.6.20.250 ppp3 20.03.2006 19:49:45 20.03.2006 20:28:25
и т.д.)

Автор: DEER 22.3.2006, 14:49
Код

 open(INFILE, ">Log.txt");
 open(FILE, "MyFile.txt");
 my $text = <FILE>;
 while($text=~/(\w*\s\w*\s\d*\s\d*\:\d*\:\d*).*?(ppp.)\s(\d*\.\d*\.\d*\.\d*)\sLOGIN/g)
 {
    my $login_date = $1;
    my $logout_date = "";
    my $ppp = $2;
    my $ip = $3;
    if($text=~/$login_date.*?(\w*\s\w*\s\d*\s\d*\:\d*\:\d*).*?$ppp\s$ip\sLOGOUT/)
    {
           $logout_date = $1;
           print <INFILE> "$ip $ppp $login_date $lodout_date";
    }
 }

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

Автор: witos 22.3.2006, 14:56
хорошо, попробую подкорректировать

Автор: nitr 22.3.2006, 16:37
Вот держи на скорую руку (рабочий но глупый):
Код

#!/usr/bin/perl -w
use strict;
my $filein = 'in.log';
my $fileout = 'out.log';
my ($login_date, $logout_date, $ppp, $ppp1, $ip, $ip1);
open OUT, ">$fileout";
open LOG, "<$filein";
while(<LOG>) {
  if(m/(\w+\s\w+\s\d+\s\d+\:\d+\:\d+).+?(ppp.)\s(\d+\.\d+\.\d+\.\d+)\sLOGIN/) { 
    $login_date = $1;
    $ppp = $2;
    $ip = $3;
  }
  if(m/(\w+\s\w+\s\d+\s\d+\:\d+\:\d+).+?(ppp.)\s(\d+\.\d+\.\d+\.\d+)\sLOGOUT/) {
    $logout_date = $1;
    $ppp1 = $2;
    $ip1 = $3;
    print OUT "$ip $ppp $login_date $logout_date\n";
  }
}
close(LOG);
close(OUT);

Автор: DEER 22.3.2006, 17:01
nitr, но не факт, что записи подключения\отключения идут поочереди smile

Автор: nitr 22.3.2006, 19:02
Этот скрипт можно улучшить, у меня щас времени нет. Я написал на скорую руку. Твой код не проверял smile

Автор: witos 22.3.2006, 19:24
DEER, это правильно подмечено, поэтому
слегка изменил код nitr, по результатам вроде похоже на правильный вид...

#!/usr/bin/perl -w
use strict;
my $filein = 'vpn.log';
my $fileout = 'my.log';
my ($login_date, $logout_date, $ppp, $ip);
open OUT, ">$fileout";
open LOG, "<$filein";
while(<LOG>) {
if(m/(\w+\s\w+\s\d*\s\d*\:\d*\:\d*).*?(ppp.)\s((\d*\.){3}\d*)\sLOGIN/) {
$login_date = $1;
$ppp = $2;
$ip = $3;
}
if ((m/(\w*\s\w*\s\d*\s\d*\:\d*\:\d*).*?(ppp.)\s(\d*\.){3}\d*\sLOGOUT/) and ($ppp eq $2)) {
$logout_date = $1;
print OUT "$ip $ppp $login_date $logout_date\n";
}
}
close(LOG);
close(OUT);

тогда остаётся только дату привести в красивый вид...

Автор: avral 23.3.2006, 09:58
Tue Mar 21 20:52:25 YEKT 2006 ppp3 10.6.20.250 LOGIN
Tue Mar 21 20:54:05 YEKT 2006 ppp5 10.6.20.240 LOGIN
Tue Mar 21 20:56:01 YEKT 2006 ppp5 10.6.20.240 LOGOUT
Tue Mar 21 20:56:33 YEKT 2006 ppp3 10.6.20.250 LOGOUT

для приведенного отрезка данных с вышеуказанным кодом теряется запись для ррр3, т. к. переменым будут присвоенны данные от ррр5.

необходимо данные ввести в массив


Автор: nitr 23.3.2006, 10:46
А можно предварительно лог-файл обработать и сделать чтобы по порядку записи были smile Думаю даже быстрей будет, т.к. остануться теже рег. выры ;)

Автор: Бонифаций 23.3.2006, 13:01
Я бы сделал так:

Код

#!/usr/bin/perl

while (<>) {
  # убираем концевые пробелы
  s/^\s+//; s/\s+$//;
  # пропускаем пустые строки
  next if /^$/;
  # делим строку лога на значения
  my ( $dow, $month, $day, $time, $tz, $year, $line, $ip, $action) = split /\s+/;
  if ($action eq "LOGIN") {
      $lines{$line} = "$ip $line $month $day $time";
   } elsif ($action eq "LOGOUT") {
      print $lines{$line}," -  "," $month $day $time\n";
   }

}




Вот результат который получился на вашем примере:

10.6.20.250 ppp3 Mar 19 23:18:54 - Mar 19 23:32:27
10.6.20.250 ppp3 Mar 20 19:49:45 - Mar 20 20:28:25
10.6.20.250 ppp3 Mar 21 20:52:02 - Mar 21 20:52:06
10.6.20.240 ppp5 Mar 21 20:54:05 - Mar 21 20:56:01
10.6.20.250 ppp3 Mar 21 20:52:25 - Mar 21 20:56:33
10.6.20.250 ppp3 Mar 21 20:58:46 - Mar 21 21:37:17

Автор: witos 23.3.2006, 13:42
И правда, что ранее написаный код терял записи....
Спасибо Бонифаций, ваш код на самом деле выдал правильный результат!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)