Самый быстрый/простой способ анализа текста

Я пытаюсь разобрать какой-то текст, ищу самое быстрое/простое решение для этого. Я пытался использовать регулярное выражение, но с Java это длится вечно...

Вот структура текста, который я пытаюсь разобрать:

*****************
ID: 1234567  // 7 digit uuid
mistakes: There may be some mistakes here, or there may not be any mistakes  //optional
mistake type: mistake background // "YES" or "NO"
report: <xml><item>blah, blah</item></xml> 

*****************

На самом деле файл может выглядеть так:

*****************
ID: 1234567
mistakes: 
NO: happened on the playground
report: <xml><item>black eye when playing basketball</item><reason>elbow</reason></xml> 

*****************

*****************
ID: 1234568
mistakes: Teacher was not watching students at the time of incident
YES: teacher turned her back after seeing an altercation
report: <xml><item>fight</item><reason>None</reason></xml> 

*****************

*****************
ID: 1234569
mistakes:
NO
report: <xml><item>Child needed band-aid</item><reason>scrape</reason></xml> 

*****************

*****************
ID: 1234570
mistakes:
NO
report: <xml><item>Child needed tissue</item><reason>runny nose</reason></xml> 

*****************
...
...

Я пытаюсь поместить «ключи» (идентификатор, ошибки, тип ошибки, отчет) в Map для дальнейшей агрегации и обработки.

Я пытался использовать регулярное выражение и добился минимального успеха, но клиент продолжает изменять структуру отчета и отбрасывает весь шаблон. Я ищу что-то, что может быть немного проще в обслуживании. В прошлом у меня было легкое время с преобразованиями xsl для данных, подобных этому, однако это не чистый xml, и я не знаю, подбросит ли Java или нет текущий формат. Я спросил клиента, готовы ли они изменить формат, но они не заинтересованы в этом.

У кого-нибудь есть мысли о том, как сделать этот синтаксический анализ проще в обслуживании?

Спасибо!


РЕДАКТИРОВАТЬ:

У меня нет с собой регулярного выражения, но вот его суть

ID:\s*(\\d{7}).*mistakes:\s*(\\d*).*mistake type:\s*(\\d*).*report:\s*(.*)


person Dan    schedule 09.04.2015    source источник
comment
Что ж, регулярное выражение должно быть довольно простым, чтобы описать этот формат, вероятно, не составит большого труда обновлять их при изменении формата.   -  person Dici    schedule 10.04.2015
comment
Каждый раз, когда я делаю обновление, это вызывает много головной боли. Кажется, что всегда что-то ломается, и мне требуется пара дней гугления и т. д., чтобы понять, почему   -  person Dan    schedule 10.04.2015
comment
Во-первых, формат не должен так часто меняться... Можем ли мы увидеть какой-нибудь код?   -  person Dici    schedule 10.04.2015
comment
Не соглашайтесь ни с одним регулярным выражением для этого. Файл имеет строгую структуру, которой вы должны следовать. По крайней мере, для последнего (отчета) вы должны разобрать отдельно как xml. Просто бегите по линиям, ожидая этой структуры, и разбивайте звезды, заполняя список ваших объектов по мере продвижения.   -  person Vedran    schedule 10.04.2015
comment
@Vedran Я уже разбираю отчет. Я пытаюсь сосредоточиться на выборе ключей (ИДЕНТИФИКАТОР, ОШИБКА, ТИП ОШИБКИ, ОТЧЕТ)   -  person Dan    schedule 10.04.2015
comment
Ключи - это просто часть строки слева от первого :... Почему это сложно? Пожалуйста, покажите какой-нибудь код   -  person Dici    schedule 10.04.2015
comment
@Dici - я сейчас дома. надо будет опубликовать, как только вернусь на работу   -  person Dan    schedule 10.04.2015
comment
@Dici - это кикер, иногда у него нет : после. Иногда это так. Я знаю, что мне нужно дать им отпор, чтобы заблокировать формат, но они слишком заняты, чтобы иметь дело с ИТ-вещами. Они пытаются разобраться с родителями и обезопасить детей.   -  person Dan    schedule 10.04.2015
comment
Я думаю, что ваш вопрос не совсем точно определен, потому что сама ваша проблема не имеет четкой спецификации, и это действительно проблема.   -  person Dici    schedule 10.04.2015


Ответы (4)


Я пока не могу комментировать посты, поэтому оставлю это как ответ. Если у вас есть фиксированное количество полей, вы можете читать строку за строкой и писать только 6 строк после того, как ваша строка начинается с ("^\.*"). Затем вы продолжите сохранять их на карте, используя аналогичную логику. Если оно начинается с ("^mistakes:"), вы сохраняете все, что осталось после удаления ":mistakes", как значение.

person Palcente    schedule 09.04.2015

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

ID: 1234567

Что-то вроде

if (line.startsWith("ID:")
{
    String id = line.subString(3).trim();
}

Очевидно, заранее проверьте, что строка не является пустой/нулевой. Я почти уверен, что это будет быстрее.

См. также эту запись в блоге Сравнение производительности: регулярные выражения и операции со строками

person Sanj    schedule 09.04.2015
comment
У меня есть более 200 таких групп для разбора. Я не хочу разбирать их построчно. - person Dan; 10.04.2015
comment
извините, не видя кода, я подумал, что используется BufferedReader. Если вы читаете весь файл в память, я все еще не вижу причины для регулярного выражения, поскольку идентификаторы элементов являются статическими. Я обычно использую регулярное выражение, если идентификаторы были чем-то вроде ID1:, ID2 и т. д. - person Sanj; 10.04.2015
comment
Если вы не рекомендуете использовать регулярное выражение, что бы вы порекомендовали? - person Dan; 10.04.2015
comment
@Dan: я проанализировал файлы с тысячами строк, используя этот тип операции. Я не думаю, что когда-либо требовалось более 2 секунд для разбора. Вы уверены, что не можете позволить себе использовать этот метод? - person Voldemort; 10.04.2015
comment
@Dan Регулярные сравнения строк, как в моем ответе. - person Sanj; 10.04.2015
comment
@Волдеморт. Я мог бы сделать это таким образом, но я искал больше элегантности. - person Dan; 10.04.2015
comment
@Dan Регулярные выражения выглядят круто и все такое, но, как вы уже знаете, их легко сломать. Это, пожалуй, лучшее решение. - person Voldemort; 10.04.2015

Я думаю, что продолжу использовать регулярные выражения с поворотом строки чтения.

Я изменю свое регулярное выражение на "\\*{17}.*\\*{17}", и как только я сгруппирую их по «*», я смогу читать их построчно, помещая их в свою карту по их идентификатору.

person Dan    schedule 09.04.2015

если вы используете java, почему бы вам не попробовать загрузить этот файл как файл свойств. И затем вы можете прочитать это, используя propFile.getProperty("key"). Таким образом, вам может не понадобиться карта, или даже если вам нужна карта, вы можете использовать propFile.propertyNames(), использовать перечисление и поместить его на карту.

person chetank    schedule 09.04.2015
comment
Проблема с этой идеей заключается в том, что одно и то же значение ключа появляется в файле несколько раз на основе примера. - person user3745362; 10.04.2015