2013-03-06 3 views
1

Я написал несколько сценариев оболочки, которые запускают маршруты трассировки на хосты, а затем сохраняет их в файл. Это отлично работает и выводит все данные в файл .log, как и предполагалось.Traceroute log to CSV Perl parser Regex issue

У меня тогда был написан простой скрипт Perl, который превращает этот .log в файл .csv, поэтому я могу импортировать его в excel. Однако, глядя на файл .csv, созданный скрипт Perl, который я написал, имеет проблемы при работе с пакетами, у которых есть IP-адреса со временем.

Например, эта строка из файла .log разбирается отлично:

1 139.222.0.1 0.941 ms 1.446 ms 1.996 ms

в файл .csv как:

1,139.222.0.1,0.941 ms,1.446 ms,1.996 ms

Однако, если трассировку вернуть что-либо подобное этому который хранится в файле .log:

12 154.54.57.98 7.579 ms 154.54.74.42 7.009 ms 130.117.0.58 7.480 ms

Затем он обрабатывается в .csv файл некорректно и губит весь следующий .csv файл (это составило пример):

11,213.248.77.134,7.432 ms,9.038 ms,213.248.70.238 ms

Как вы можете видеть IP заданный с время перехвата теперь используется как время, необходимое для пакета.

Я очень смущен, как исправить это! Любая помощь будет оценена, вот фрагмент кода, который превращает журнал в формате CSV для каждого прыжка:

my $start = "'Hop','IP','T1','T2','T3'"; 
    print OUTPUT "\n$_$start\n"; 
}; 

    print OUTPUT "$1,$2,$3 ms,$4 ms,$5 ms\n" if (/(\d+)\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+ms\s+(\S+)/); 

EDIT

написал свой собственный исправление, добавляет дополнительные столбцы CSV и вкладыши в них соответствующим образом

my $start = "'Hop','IP','T1','T1IP','T2','T2IP',T3'"; 
    print OUTPUT "\n$_$start\n"; 
}; 

if (/(\d+)\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+ms\s+(\S+)\s+ms/){ 
print OUTPUT "$1,$2,$3 ms, ,$4 ms, ,$5 ms\n"; 

}elsif (/(\d+)\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+ms/){ 
print OUTPUT "$1,$2,$3 ms,$4,$5 ms, ,$6 ms\n"; 

}elsif (/(\d+)\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+ms\s+(\S+)\s+(\S+)\s+ms/){ 
print OUTPUT "$1,$2,$3 ms, ,$4 ms,$5,$6 ms\n"; 

}elsif (/(\d+)\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+(\S+)\s+ms\s+(\S+)\s+(\S+)\s+ms/){ 
print OUTPUT "$1,$2,$3 ms,$4,$5 ms,$6,$7 ms\n"; 
}; 

Спасибо за вашу помощь/ответы!

+0

Пожалуйста, покажите код, который не работает – Borodin

+0

код, который работает Isnt print OUTPUT "$ 1, $ 2, $ 3 ms, $ 4 ms, $ 5 ms \ n" if (/ (\ d +) \ s + (\ S +) \ s + (\ S +) \ s + ms \ s + (\ S +) \ S + мс \ S + (\ S +) /); как эта учетная запись только в том случае, если traceroute возвращает только значения времени, а не время и значения IP –

ответ

0

Для данных, которые вы показываете, я бы просто разделил строку на пробел, а не ms.

my $csv = join ',', split /\s+(?!ms)/, $line; 

Но код, который вы показываете, означает, что информация маршрута маршрута смешана с датами, поэтому это может быть неприемлемо.

Update

Просмотрев свои данные, я думаю, что это должны делать то, что вы хотите.

Обратите внимание, что имена заголовков, которые вы печатаете, не соответствуют данным, в которых у вас более одного IP-адреса на линии. Я не уверен, что вы хотите сделать в этом случае.

#!/usr/bin/perl 

use strict; 
use warnings; 
use autodie; 

my $logfile = 'trace.log'; 
my $parsedfile = 'trace.csv'; 

open my $infh, '<', $logfile; 
open my $outfh, '>', $parsedfile; 

while (<$infh>) { 
    if (/^[a-z]{3}\s+[a-z]{3}/i) { 
     print $outfh $_; 
     print $outfh qq{"Hop","IP","T1","T2","T3"\n}; 
    } 
    elsif (/^\s*\d/) { 
     chomp; 
     s/^\s+//; 
     print $outfh join(',', split /\s+(?!ms)/), "\n"; 
    } 
} 

выход

Wed Mar 6 01:58:49 GMT 2013 
"Hop","IP","T1","T2","T3" 
1,139.222.0.1,0.987 ms,1.412 ms,1.971 ms 
2,10.0.0.1,0.445 ms,0.500 ms,0.552 ms 
3,172.16.0.34,1.667 ms,0.875 ms,1.503 ms 
4,193.62.92.71,1.939 ms,2.547 ms,2.529 ms 
5,146.97.130.249,2.561 ms,2.447 ms,4.615 ms 
6,146.97.65.85,5.309 ms,6.709 ms,5.376 ms 
7,146.97.65.65,7.133 ms,7.340 ms,7.323 ms 
8,146.97.65.37,9.362 ms,9.750 ms,9.804 ms 
9,146.97.35.125,9.473 ms,9.485 ms,8.815 ms 
10,213.248.84.177,8.798 ms,9.171 ms,8.505 ms 
11,213.248.77.134,8.333 ms,7.837 ms,213.248.70.238,7.721 ms 
12,154.54.74.42,7.879 ms,154.54.72.186,7.450 ms,154.54.57.94,7.862 ms 
13,66.28.4.189,81.812 ms,81.433 ms,154.54.30.129,80.648 ms 
14,154.54.30.17,217.548 ms,154.54.43.10,217.531 ms,66.28.4.222,109.029 ms 
15,154.54.27.53,216.490 ms,154.54.42.241,195.393 ms,154.54.27.53,216.389 ms 
16,154.54.42.241,195.141 ms,193.123 ms,192.900 ms 
17,154.54.28.85,99.232 ms,154.54.5.229,99.127 ms,98.931 ms 
18,154.54.31.21,102.739 ms,154.54.5.229,99.086 ms,98.803 ms 
19,154.54.31.21,102.719 ms,38.122.60.46,101.206 ms,101.052 ms 
20,216.234.104.254,102.619 ms,38.122.60.46,101.415 ms,101.275 ms 
21,75.98.163.130,100.512 ms,100.409 ms,100.485 ms 
+0

вещь даты просто как заголовок и печатается только один раз в начале файла log/csv, поскольку этот маршрут трассировки повторяется повторно и Мне нужно это для справки, нет никаких других дат, напечатанных после запуска traceroute :) спасибо за ваш ответ, плохо посмотрите на этот метод спасибо –

+0

Поняв, что вы задали вопрос лучше, я думаю, что мое решение может быть неуместным. Образец полного ввода будет полезен. – Borodin

+0

Спасибо Бен. Я обновил свой ответ, чтобы обеспечить то, что я считаю рабочей программой. – Borodin

0

Предположение о том, что вы хотите, без кодов заголовка:

my $re_ip = qr/\d+\.\d+\.\d+\.\d+/; 
while(<INPUT>) { 
    my @v = split(/($re_ip)/); 
    my $hop = (shift(@v) =~ /(\d+)/)[0]; # the hop number? 
    for my $v (@v) { 
    if ($v =~ /$re_ip/) { 
     print OUTPUT "$hop,$v,"; 
    } else { 
     my @ms = $v =~ /(\S+\s+ms)/g; 
     print OUTPUT join(",", @ms), "\n"; 
    } 
    } 
} 
+0

Спасибо за ваш ответ, я тоже посмотрю на это :) –