2009-03-05 8 views
1

У меня есть огромный набор строк журнала, и мне нужно разобрать каждую строку (так что эффективность очень важна).Разбор строки в C++

Каждая строка журнала имеет вид

CUST_NAME TIME_START time_end (IP или URL) *

Так IP-адрес, время, время и, возможно, пустой список IP-адресов или URL-адресов, разделенных точкой с запятой. Если в последнем списке есть только ip или url, разделителя нет. Если больше 1, то они разделяются точкой с запятой.

Мне нужен способ разобрать эту строку и прочитать ее в структуре данных. time_start или time_end может быть либо системным, либо GMT. cust_name также может иметь несколько строк , разделенных пробелами.

Я могу это сделать, читая характер по характеру и в сущности написав свой собственный парсер. Есть ли лучший способ сделать это?

+0

Хммм ... можете ли вы гарантировать, что полуколоны не появятся в ваших URL-адресах? Или, по крайней мере, они не появляются в конце? – dmckee

+0

Какую цель? что вы собираетесь делать с данными после его анализа? – hasen

ответ

7

Возможно, Boost RegExp lib поможет вам. http://www.boost.org/doc/libs/1_38_0/libs/regex/doc/html/index.html

+0

Я модернизировал, но помню: «У тех, кто пытается решить проблему с использованием регулярных выражений, есть две проблемы». –

+0

:) хорошая цитата. Но в любом случае RegExp подходит для небольших или незначительных задач. – bayda

1

Пользовательский вход требует пользовательский парсер. Или, молитесь, чтобы существовал идеальный мир, и ошибок не существует. Специально, если вы хотите иметь эффективность. Проводка некоторого кода может помочь.

0

Вы можете попытаться использовать простой лексический словарь lex/yacc | flex/bison для анализа такого ввода.

2

Рассмотрим с помощью Regular Expressions library ...

+0

И следующее, что вы знаете, у нас есть ** другое **, как разобрать вопрос о URL-адресах. – dirkgently

3

Почему вы хотите сделать это в C++? Это похоже на очевидную работу для чего-то вроде perl.

+0

Несомненно. Если он просто выполняет эту работу. Но контекст может быть уже существующим кодом с какой-то другой основной задачей ... – dmckee

+0

Он заинтересован в производительности, и пользовательский парсер C++ выдувает двери от парсера Perl для скорости выполнения (но * не * скорости разработки). –

+0

Дэвид, это не обязательно так. Это может очень легко отразиться на нем (с точки зрения производительности), если он сохранит полученную гигантскую структуру данных в памяти! C++ там не поможет. – hasen

5

У меня был успех с Boost Tokenizer для такого рода вещей. Это помогает вам разбить входной поток на токены с пользовательскими разделителями между токенами.

4

Использование регулярных выражений (boost::regex хорошая реализация для C++), вы можете легко отделить различные части вашей строки - cust_name, time_start ... и найти все, что urls \ ips

Второй шаг - это более подробный разбор этих групп, если это необходимо. Даты, например, можно анализировать с использованием библиотеки boost::datetime (запись пользовательского парсера, если формат строки не является стандартным).

1

ОБНОВЛЕНИЕ изменен ответ решительно!

У меня есть огромный набор строк журнала, и мне нужно разобрать каждую строку (так что эффективность очень важна).

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

Эффективность, в которой вы действительно нуждаетесь, - это не производительность на уровне машинного кода кода разбора, а на общем уровне алгоритма.

Подумайте, что вы пытаетесь сделать.
У вас есть огромный текстовый файл, и вы хотите, чтобы преобразовать каждую строку в структуру данных,

Сохранение огромную структуру данных в памяти очень неэффективна, независимо от того, какой язык вы используете!

Что вам нужно сделать, это «выборка» по одной строке за раз, преобразовать ее в структуру данных и затем обработать ее, и только после того, как вы закончите работу с структурой данных, вы идете и выбираете следующую строку и преобразуйте ее в структуру данных, обработайте ее и повторите.

Если вы это сделаете, вы уже решили главное узкое место.

Для разбора строки текста, кажется, формат ваших данных весьма упрощенно, проверьте аналогичный вопрос, который я задал некоторое время назад: C++ string parsing (python style)

В вашем случае, я полагаю, вы можете использовать строку и используйте оператор >>, чтобы прочитать следующую «вещь» в строке.

см. this answer например код.

В качестве альтернативы (я не хотел удалять эту часть!) Если бы вы могли написать это в python, это будет намного проще. Я не знаю вашу ситуацию (это, кажется, что вы застряли с C++), но до сих пор

Посмотрите на эту презентацию для выполнения этих видов задачи эффективного использования питона генератора выражений: http://www.dabeaz.com/generators/Generators.pdf

Это стоит читать , На слайде 31 он имеет дело с тем, что кажется чем-то очень похожим на то, что вы пытаетесь сделать.

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

+0

Я думаю, что вы объединяете хорошую идею (обрабатываете по одной строке за раз) с той, которая зависит от контекста (не используйте для этого C++). Более того, OP отмечает в комментариях к другому ответу, что он делает это в существующем коде C++. Тем не менее, +1 для одноразовой точки. – dmckee

+0

хорошо пункт! Я изменил ответ. но в моей защите, хотя он упомянул о существующем приложении C++ довольно долго после того, как я отправил свой ответ – hasen

0

Парсер, который вам нужен, звучит очень просто. Take a look at this. Любой скомпилированный язык должен иметь возможность анализировать его с очень высокой скоростью. Тогда это вопрос о том, какую структуру данных вы создаете. & save.