У вас есть возможность отучиться от регулярного выражения, но, надеюсь, это не будет слишком болезненным. Самым большим виновником вашего мышления является использование этой конструкции:
some_stuff + Regex(".*") +
Suppress(string_representing_where_you_want_the_regex_to_stop)
Каждый подпарапер внутри синтаксического анализатора является в значительной степени автономным и работает последовательно через входящий текст. Таким образом, термин Regex не может заглянуть к следующему выражению, чтобы увидеть, где остановится повторение '*'
. Другими словами, выражение Regex(".*")
будет просто читать до конца строки, поскольку именно здесь ".*"
останавливается без указания многострочного.
В pyparsing эта концепция реализована с использованием SkipTo. Вот как написана ваша строка заголовка:
header = Suppress("[**] [") + Combine(integer + ":" + integer + ":" + integer) +
Suppress("]") + Regex(".*") + Suppress("[**]")
Ваша проблема ". *" Будет решена путем изменения ее на:
header = Suppress("[**] [") + Combine(integer + ":" + integer + ":" + integer) +
Suppress("]") + SkipTo("[**]") + Suppress("[**]")
То же самое для кл.
Последняя ошибка, ваше определение даты короткое на один ':' + integer:
date = integer + "/" + integer + "-" + integer + ":" + integer + "." +
Suppress(integer)
должно быть:
date = integer + "/" + integer + "-" + integer + ":" + integer + ":" +
integer + "." + Suppress(integer)
Я думаю, что этих изменений будет достаточно, чтобы начать анализ данных вашего журнала.
Вот некоторые другие предложения по стилю:
У вас много повторных Suppress("]")
выражений. Я начал определять все свои подавляемые знаки препинания в очень компактном и простом в обращении утверждении, например:
LBRACK,RBRACK,LBRACE,RBRACE = map(Suppress,"[]{}")
(разверните, чтобы добавить любые другие знаки препинания, которые вам нравятся). Теперь я могу использовать эти символы по их символическим именам, и нахожу полученный код немного легче для чтения.
Вы начинаете с заголовка с header = Suppress("[**] [") + ...
. Мне никогда не нравилось видеть пробелы, встроенные в литералы таким образом, так как он обходит некоторые из парсинга, который дает автоматическую пропускную способность при разборе. Если по какой-либо причине пробел между «[**]» и «[» был изменен на использование 2 или 3 пробелов или табуляции, то ваш подавленный литерал потерпит неудачу. Объедините это с предыдущим предложением, и заголовок начнется с
header = Suppress("[**]") + LBRACK + ...
Я знаю, что это сгенерированный текст, поэтому изменение в этом формате маловероятно, но оно лучше подходит для сильных сторон pyparsing.
Как только вы разберете свои поля, начните присваивать имена результатов различным элементам вашего парсера. Это сделает лот более простым для последующего получения данных. Например, измените cls на:
cls = Optional(Suppress("[Classification:") +
SkipTo(RBRACK)("classification") + RBRACK)
Позволит вам получить доступ к данным классификации, используя fields.classification
.