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


Автор: rMaveric 7.1.2005, 04:30
Нужно парсить файлы различных форматов и составление по ним отчетов.
Файлы логи Апача, Сквида и подобных серверов...

Формат изменяем. Для скана использую регулярные выражения.

проблема.

1. Если я читаю файл построчно
Код

while (!feof($fp))
  {
  $data . =fgets($fp, 1024);
  }

Проблема: Ужастные тормоза при чтении

2. Читаю другой функцией.
Код

while (!feof($fp))
  {
  $data . =fread($fp, 1024);
  }

Проблема: Читает только первые 100 срок

3. Читаю в масив
Код

while (!feof($fp))
  {
  $data[]  =fgets($fp, 1024);
  }

Проблема: Читает очень быстро. Парсит невероятно долго.

Перепробовал все что только мог придумать.
парсить логи нужно около 100Мб лог... и нужно быстро

Автор: Secandr 7.1.2005, 09:33
rMaveric smile
А зачем тебе читать весь файл? Ты же его разбираешь регами, вот и разбирай каждую строчку отдельно.
У меня логи squid`а за месяц парсятся менее 2 секун. При этом пользователей несколко сотен. Правда написан грабер на перле. Перл изночально создавался для работы с потоками данных.

Автор: rMaveric 7.1.2005, 12:09
2 Secandr
дно из принцыпиальный требований ПХП не мой каприз. Я и так использую перл совместимые и если не ошибась эти функции (не считая маленьких отличий) братья близнецы написаные на сишке и в ПХП и в Перде.

Я бы с удовользствием парсил построчно, вот думаю вот о какой проблеме. мне все это дело, кроме отчета в базу нужно. И мне показалось проще было бы пропарсить целиком... Но сейчас проследил объемы памяти сжираемые и понял что ошибаюсь. поэтому буду наверно парсить построчно и голову не морочить. Спасибо

Автор: Mal Hack 7.1.2005, 14:16
rMaveric
можно попробовать поработать с потоками напрямую, но я об этом только слышал.
Второй вариант, попробуй file();, я не замерял, но имхо он может быстрее файл читать...

Автор: rMaveric 7.1.2005, 14:33
2 Mal Hack
file() работает с тойже скоростью как и
Код

while (!feof($fp))
 {
 $data[]  =fgets($fp, 1024);
 }


Но что-то в таком случае тормоза при парсинге...

Помогите. может я не логично прописал правило?

Код

$parse_string = '/([^\x20]+)\x20([^\x20]+)\x20([^\x20]+)\x20\[(\d{2})\/(\w{3})\/(\d{4}):(\d{2}):(\d{2}):(\d{2}).+(\d{4})\]\x20\"([^\x20]+)\x20([^\x20]+)\x20([^\/]+)\/(.{3})\"\x20(\d{3})\x20(\d+|-)\x20\"(http:\/\/[^\/]+)([^\"]+)\"\x20\"(.+)\"/xi';
preg_match_all($parse_string, $log_content, $matches);


Нужно парсить лог апача
192.168.0.27 - - [04/Jan/2005:03:01:50 +0000] "GET / HTTP/1.1" 200 18184 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0"

Автор: Mal Hack 7.1.2005, 14:41
Код

preg_match_all('!^([^ ]+) ([^ ]+) ([^ ]+) \[([^\]]+)\] "([^ ]+) ([^ ]+) ([^/]+)/([^"]+)" ([^ ]+) ([^ ]+) ([^ ]+) (.+)!',  $line_in,  $elements)

Вывод:
Код
Array (
   [0] => 195.158.13.251 - - [30/Sep/2004:01:21:45 +0400] "GET /folder/file.php HTTP/1.1" 200 1869 "http://site.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)"
   [1] => 195.158.13.251
   [2] => -
   [3] => -
   [4] => 30/Sep/2004:01:21:45 +0400
   [5] => GET
   [6] => /folder/file.php
   [7] => HTTP
   [8] => 1.1
   [9] => 200
   [10] => 1869
   [11] => "http://volodin.net/"
   [12] => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)" )

Автор: IZ@TOP 7.1.2005, 15:47
rMaveric, нет, file работает быстрее, я уже замерял.

Автор: Secandr 7.1.2005, 16:06
Сейчас посмотрел на свою софтину, оказалось что логи сквида я читаю полностью, только логи у меня разбиты по дням smile

Автор: IZ@TOP 7.1.2005, 16:11
Secandr, я кстате тож писал как то обработчик логов, только для логов по стандарту W3C.
Незнаю правда сохранилась у меня эта штука или нет...

Автор: Secandr 7.1.2005, 17:06
IZ@TOP У меня точно сохранилась. У всего офиса из зарплаты по 200-500р вычитает smile


rMaveric Может лучше логи правильно складывать - не в один файл, а по дням или неделям. Логи за день обрабатываются довольно легко. И если посадить скрипт на крон, а результаты писать в БД, то всё летает.

Автор: Opik 7.1.2005, 17:08
rMaveric а попробуй:
file_get_contents();

Автор: rMaveric 7.1.2005, 17:11
2 Mal Hack
Спасибо. слегка проапгрейдил твою строку.. И получилось то что нужно smile мне еще нужно было дату, время и часовой поя бить. А так спасибо огромное. Скорость обработки увеличилась ровно в 6 раз.

2 IZ@TOP
Только что замерил. Одинаково. ТОчнее разное но зависит от пятен на луне и от магнитного поля юпитера.

И я сейчас пишу парсинг ВСЕВОЗМОЖНЫХ логов с возможностью настройки. Так что если вдруг кому... мне будет не жалко поделиться.
Добавлено @ 17:12
2 Secandr
Нет не правельно smile
Мне не только свои логи нужно обрабатывать....

Автор: rMaveric 10.1.2005, 00:19
Еще вопрос. в тему.

Кто может порекомендовать ХОРОШУЮ доку или на худой ... книгу по составлению регулярных выражений? Требуется не учебник с описанием что означает тот или иной клас и подобное. А именно разъяснение насчет оптимизации выражния. В каких случаях и что лучше использовать для достижения максимальной производительности. Просто одно и тоже действие зделать можно 1 миллионом способов, но не понятно какой из них более рационален в той или иной ситуации. smile

Автор: Secandr 10.1.2005, 09:56
Книга O`Relly "Регулярные выражения". Там описан принцип и механизм действия регов, а так же оптимизация. После прочтения думать будешь по другому...

Автор: Sardar 10.1.2005, 10:32
После этого полезно разобраться с формальными грамматиками, в частности простыми в теории регулярными выражениями.

Автор: rMaveric 10.1.2005, 13:00
2 Sardar && Secandr
Большое спасибо. На сиим все. Тему можно закрывать.

Автор: r00t 10.1.2005, 16:40
poprobuy awk, ne dumayu chto regi v etom sluchie celesobrazni, ili v samom ploxom variante poprobuy grep on vsyo taki binarniy, po bistree budet ...

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