![]() |
Создание sql-скрипта для переноса txt в mysql
Есть txt файл с логами, нужно его перенести в таблицу mysql. Вот пример лога:
03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 "200 OK gzip" А вот нужно его поместить в таблицу с колонками (date,time,user,ip,url,size,re,cache,pr,send,otv). Не могу разделить значения с "/". Возможно ли сделать это через sql или нужно дополнительно обрабатывать скриптом? |
На perl:
Код:
$date,$time,$user,$ip,$url,$size,$re,$cache,$pr,$send,$otv = split (' ', $stroka); Цитата:
|
А как сделать, что бы он читал из файла эти данные?
|
Цитата:
Гм. это по моему просто разбиение строки находящейся в $stroka разделенной пробелами и рассовывание результатов по скалярным переменным. Т. к. оператор split всегда возвращает результат как массив, то здесь неявно используется массив по умолчанию @_ Т.е. результаты split присваиваются массиву, а затем элементы массива присваиваются отдельным скалярным переменным. 2) В качестве зачачи пробела как разделителя, грамотнее использовать не ' ', а следующую конструкцию: $date,$time,$user,$ip,$url,$size,$re,$cache,$pr,$send,$otv = split /\s+/, $stroka; 3) Простейшее чтение из файла, где имя файла задается в параметрах вызова perl-программы выглядит так: use strict; while (<>) { chomp; # удаление Enter, LF, и подобного # print "Чо за $_"; Проверка считанного $date,$time,$user,$ip,$url,$size,$re,$cache,$pr,$send,$otv = split /\s+/, $_; # SQL вызов } # чтение происходит построчно, т. е. файл зараз целиком не считывается, что делает возможным обработку очень больших файлов # Если имя обрабатываемого файла не указана (нет параметров вызова), то читается стандартный ввод, до Ctrl-Z - win, Ctrl-D - Unix |
Так же нужно помнить, что элемент "200 OK gzip" содержит внутри себя пробелы.
Соответственно, нужно вводить более строгие правила, а не просто разбиение по пробельным символам |
|
Код (используется ActivePerl 5.10.1)
#! c:\Perl\bin\perl.exe -w use strict; my $some_input="03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 \"200 OK gzip\""; print "$some_input\n"; my @args=split/\s+/, $some_input; foreach (@args) { print "$_ \n"; } print "---------------------------------------------------------\n"; Результат: 03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 "200 OK gzip" 03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 "200 OK gzip" --------------------------------------------------------- Цитата:
(...) = split /\s+/,$stroka; |
да это все хорошо, но вот возможно ли еще \ поубирать? А то у меня и так данные в таблицу попадали
|
Цитата:
Только мне нужен пример разбора имеющейся строки такого плана date,time,user,ip,url,size,re,cache,pr,send,otv Имеем: 03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 "200 OK gzip" Надо: date=03.03.2010 time=19:03:21 user=fox ip=192.168.2.10 url=http://yandex.ru и так до otv= 2) Пример соединения с mySQL я приведу попозжа |
Цитата:
|
Цитата:
1) это единственный язык где регулярные выражения родные, а не прикручены при помощи классов, как в C# - например. 2) Perl создан как обработчик лог-файлов и это он делает гораздо лучше остальных 3) Решил потренироваться, давно не брал в руки шашку :) ================================= Использование модуля DBI #! c:\Perl\bin\perl.exe -w use DBI; # Заменить dbname, mysqlserver.domain.com, db_username, password на реальные данные $dbh=DBI->connect('DBI:mysql:dbname:mysqlserver.domain.com:3306', 'db_username', 'password', {RaiseError=>1}) or die "connecting : $DBI::errstr\n"; # 03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 "200 OK gzip" # date,time,user,ip,url,size,re,cache,pr,send,otv # Предполагаем , что переменные уже присвоены $date='03.03.2010'; $time='19:03:21'; $user='fox'; $ip='192.168.2.10'; $url='http://yandex.ru'; $size=7020; $re=7020; $cache=493; $pr='100%'; $send='999'; $otv='200 OK gzip'; # Конверсии printf # %g - число # %d - десятичное целое # %s строка # %f - число с плавающей запятой # Подготовка строки -шаблона SQL оператора my $sql_fmt= "INSERT INTO tablename VALUES(%s, %s, %s, %s, %s, %d, %d, %d, %s, %d, %s)"; # Формирование SQL-запроса, column_name заменить на реальные имена столбцов my $sql=sprintf($sql_fmt, $date->column_name, $time->column_name, $user->column_name, $ip->column_name, $url->column_name, $size->column_name, $re->column_name, $cache->column_name , $pr->column_name, $send->column_name, $otv->column_name); # вызов $dbh->do ($sql); $dbh->disconnect; |
Разложение строки при помощи регулярных выражений в Perl
#! d:\Perl\bin\perl.exe -w #use strict; my $some_input="03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 \"200 OK gzip\""; # date,time,user,ip,url,size,re,cache,pr,send,otv chomp $some_input; print "$some_input\n"; print "begin---------------------------------------------------------\n"; $some_input =~ m{^([0-9]{1,2}.[0-9]{1,2}.[0-9]{2,4})/([0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})\b \b(\w+)/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\b \b(\S+)\b \b(\d+)\b \b(\d+)/(\d+)\b \b(\d+)% \b(\d+)\b (.*)$}; my $date=$1; my $time=$2; my $user=$3; my $ip=$4; my $url=$5; my $size=$6; my $re=$7; my $cache=$8; my $pr=$9; my $send=$10; my $otv=$11; print " $date\n $time\n $user\n $ip\n $url\n $size\n $re\n $cache\n $pr\n $send\n $otv\n"; print "end---------------------------------------------------------\n"; Кстати. Хозяйке на заметку :) Обрабатываемый файл, как я понимаю, представляет собой один из форматов формат apach В таком формате данные отдает: SQUID и Apach в режиме акселератора. |
Вложений: 1
Так как сервер может покоцать код, добавляю как файл
|
kim-aa, браво!
Цитата:
Цитата:
|
Сейчас бы еще разобраться, как его запустить. Не ругайтесь сильно, но я не знаю как это. У меня есть перл + у меня Windows
|
1) Скачиваете ActivePerl
2) Скачиваете Notepad++ из приложенного архива, им удобно просматривать код предварительно выбрав Language\Perl 3) Инсталируете ActivePerl 4) Распаковываете Notepad 5) Скачиваете полученный код и переименовываете его в ro-0.pl и кладете ну скажем в корень D:\ 6) Запускаете CMD 7) D:\ 8) perl ro-0.pl Очень помагает наличие FAR или TotalCMD |
Склероз, простите
|
Вариант, возможно более наглядный для новичка.
Сначала производятся замены на Tab как разделитель столбцов. Потом полученная строка разбирается Split #! d:\Perl\bin\perl.exe -w use strict; my $some_input="03.03.2010/19:03:21 fox/192.168.2.10 http://yandex.ru 7020 7020/493 100% 999 \"200 OK gzip\""; print "$some_input\n"; #Замена "/ цифра" на "/Tab" $_=$some_input; s{/(\d)}{\t$1}g; my $tmp=$_; #Замена ":21 fox" на ":21(Tab)fox" $_=$tmp; s{(:\d\d) (\w)}{$1\t$2}; $tmp=$_; #Замена ".xxx http" на ".xxx(Tab)http" $_=$tmp; s{(.\d{1,3}) (\w)}{$1\t$2}; $tmp=$_; #Замена ".ru 7020" на ".ru(Tab)7020" $_=$tmp; s{(\S) (\d)}{$1\t$2}; $tmp=$_; #Замена "7020 7020" на "7020(Tab)7020" $_=$tmp; s{(\d) (\d)}{$1\t$2}; $tmp=$_; #Замена "493 100%" на "493(Tab)100%" $_=$tmp; s{(\d) (\d+%)}{$1\t$2}; $tmp=$_; #Замена "100% 999" на "100%(Tab)999" $_=$tmp; s{(\d+%) (\d)}{$1\t$2}; $tmp=$_; #Замена "999 \" на "999(Tab)\" $_=$tmp; s{(\d) }{$1\t}; $tmp=$_; print "$tmp\n"; my @args=split/\t/, $tmp; print "begin---------------------------------------------------------\n"; foreach (@args) { print "$_ \n"; } print "end---------------------------------------------------------\n"; |
kim-aa Большое спасибо за код. Но как прописать, что бы исходные данне он брал из текстового файла?
|
foxintel,
Файлик приведите, я на нем и попробую. И приведу образец кода. ЗЫ. Будущий урок будет называться дескрипторы в Perl :) |
Вложений: 1
Вот пример файла))) еще хотел уточнить, это лог файл прокси сервера handycache
|
1) вот забор данных из файлика
Кстати формат отличается слегка от описанного вами: - разделение в исходном файле табуляцией - есть неопознанный "хвост" - пихается в переменную $hz :) #! d:\Perl\bin\perl.exe -w #use strict; # filename my $full_file_name='d:\home\kim\perl\03.03.2010#18_59_51.txt'; # открытие десктора файла, если не найдено - аварийный выход с сообщением об ошибке open HANDYCACHE, "< $full_file_name" or die "Cannot open file: $full_file_name. System state: $!"; # построчное чтение, до конца файла while (<HANDYCACHE>) { # чтение каждой строки происходит в переменную по умолчанию $_ my $some_input=$_; #my $some_input='03.03.2010/19:09:27 fox/192.168.2.10 http://www.playground.ru/images/f2.gif 960 960/0 100% 0 "200 OK From Cache (HC)" Н.5'; # date,time,user,ip,url,size,re,cache,pr,send,otv,hz chomp $some_input; # отладочный вывод на экран считанной строки #print "$some_input\n"; #print "begin---------------------------------------------------------\n"; # #-----------------------------------------03.03.2010------------------------------------------------/19:03:21-----------------------------------------------tab-----------fox/192.168.2.10 ----------------------------------------------------------------------------tab---http://yandex.ru -------7020-------tab-------7020/493 ----------tab--------100% ---tab----999 -------tab--"200 OK From Cache (HC)"-------Н.5; $some_input =~ m{^([0-9]{1,2}.[0-9]{1,2}.[0-9]{2,4})/([0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})\b\s+\b(\w+)/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\b\s+\b(\S+)\b\s+\b(\d+)\b\s+\b(\d+)/(\d+)\b\s+\b(\d+)%\s+\b(\d+)\b\s+(".*")\s+(.*)$}; my $date=$1; my $time=$2; my $user=$3; my $ip=$4; my $url=$5; my $size=$6; my $re=$7; my $cache=$8; my $pr=$9; my $send=$10; my $otv=$11; my $hz=$12; # отладочный вывод на экран разобранной строки print " $date\n $time\n $user\n $ip\n $url\n $size\n $re\n $cache\n $pr\n $send\n $otv\n $hz\n"; # отладочная заглушка на выполнение одного прохода #last; # SQL вызовы } print "end---------------------------------------------------------\n"; close HANDYCACHE; 2) С SQL операторами пример приведен в приложенном файлике. Проверить не могу, за отсутствием MySQL |
Вложений: 1
RAR
|
Время: 16:31. |
Время: 16:31.
© OSzone.net 2001-