2015-03-04 3 views
3

Я пытаюсь проанализировать записи журнала в приложении C#, используя это регулярное выражение: (^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3})(?!\1) для журналов в формате [дата (в некотором формате)] | [уровень] | [appname] | [сообщение].Разбор многострочных записей журнала с использованием регулярного выражения

Где (я думаю):

  • ^ спичках начало строки (включен на regex101)
  • [0-9]{4}(-[0-9]{2}){2}, за которой следует начинать с даты как 2015-03-03
  • ([^|]+\|){3}) следует остальным даты, уровень журнала и имя приложения
  • (?!\1) следует не начало новой записи в журнале (должно быть сообщение)

К примеру, у меня есть следующие записи журнала (разделенные символом новой строки для уточнения):

 
2015-03-03 19:30:47.2725|INFO|MyApp|This is a single line log message. 

2015-03-03 19:31:29.1209|INFO|MyApp|This log message has multiple 
lines with 
2015-03-03 
a date in it. 

2015-03-03 19:32:50.1106|INFO|MyApp|This log message has 
multiple lines 
but just text only. 

2015-03-03 19:33:20.2683|ERROR|MyApp|This log message has multiple lines but 
also some confusing text like 
2015-03-03 19:33:20.2683|ERROR| which should 
still be a valid log message. 

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

Если я включаю .* в регулярном выражении: (^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3}).*(?!\1) он соответствует сообщение, но только одну строку (потому что . не соответствует новой строки).

Итак, как я могу захватить (многострочное) сообщение?

+0

какой язык вы используете Вот? существует несколько различных типов регулярных выражений в зависимости от среды, поэтому, пожалуйста, будьте конкретны. – phillip

+0

@phillip Я хочу использовать его в приложении C#, но сначала я попытался заставить его работать, используя PHP-код по умолчанию regex101. –

ответ

3

Вы можете использовать это регулярное выражение:

(^\d{4}(-\d{2}){2}([^|]+\|){3})([\s\S]*?)\n*(?=^\d{4}.*?(?:[^|\n]+\|){3}|\z) 

RegEx Demo

Это регулярное выражение должно работать в C#, а также, просто убедитесь, что использовать MULTILINE флаг.

+1

это работало в моем тестировании. – phillip

+0

@anubhava Спасибо за ваш ответ, но у меня такая же проблема, как я только что прокомментировал [ответ Necreaux] (http://stackoverflow.com/a/28864065/465942) –

+0

Я читал, но не понимаю, для чего ситуация не работает. Можете ли вы обновить демо-ссылку и предоставить мне обновленную ссылку regex101, показывающую, что не работает. – anubhava

-2

Что вы хотите использовать в регулярном выражении? В Java, например, есть флаг для указания «.». для соответствия символам новой строки.

следующее регулярное выражение, как представляется, сделать трюк:

/(([0-9]{4})(-[0-9]{2}){2}([^|]+\|){3})((.(?!\2))*)/sg 

Модификации я сделал для вашего запроса были в основном некоторые очистки (ваша дата съемки группа была неправильно). Затем я добавил. и * в этой заключительной группе захвата. https://regex101.com/r/fU1vV1/2

Важнейшей частью является использование флагов sg. g позволяет получить все совпадения. s заставляет его рассматривать все как одну строку (иначе ваш негативный взгляд никогда не будет работать). Все это было бы лишним, если бы вы могли гарантировать, что комментарии были в одной строке (что они в вашем примере), так как вы могли просто захватить до конца строки.

+0

@Necreaux Похоже, что ваш ответ действительно работает! Я вижу, что вместо этого вы используете модификатор 's' (single line). Не могли бы вы объяснить поясное выражение шаг за шагом здесь, как и я, чтобы я и другие могли учиться на этом? (Вместо ссылки, которая может быть сломана когда-нибудь) –

+0

Добавлена ​​дополнительная очистка/очистка. – Necreaux

+0

@Necreaux Теперь я вижу, что когда у меня есть сообщение журнала, которое содержит саму дату (или только год), сообщение больше не включается в регулярное выражение. Сообщение журнала должно быть вечным, кроме начала нового сообщения журнала, которое может быть обнаружено в формате журнала, который я описал. Какие-либо предложения? –

3

Нечто подобное должно работать.
См. Комментарии в регулярном выражении.
(мода: сделать разрыв строки опционно для EOS или сообщения одной линии)

@"(?m)^[0-9]{4}(?:-[0-9]{2}){2}(?:[^|\r\n]+\|){3}((?:(?!^[0-9]{4}(?:-[0-9]{2}){2}(?:[^|\r\n]+\|){3}).*(?:\r?\n)?)+)" 

Форматированная (with this):

(?m)       # Modifier - multiline 
^        # BOL 
[0-9]{4}      # Message header 
(?: - [0-9]{2}){2} 
(?: [^|\r\n]+ \|){3} 
(       # (1 start), The Message 
     (?: 
      (?!       # Assert, not a Message header 
       ^       # BOL 
       [0-9]{4} 
       (?: - [0-9]{2}){2} 
       (?: [^|\r\n]+ \|){3} 
      ) 
      .*       # Line is ok, its part of the message 
      (?: \r? \n)?     # Optional line break 
    )+ 
)        # (1 end) 

Выход:

** Grp 0 - (pos 0 , len 74) 
2015-03-03 19:30:47.2725|INFO|MyApp|This is a single line log message. 


** Grp 1 - (pos 36 , len 38) 
This is a single line log message. 

-------------- 

** Grp 0 - (pos 74 , len 108) 
2015-03-03 19:31:29.1209|INFO|MyApp|This log message has multiple 
lines with 
2015-03-03 
a date in it. 


** Grp 1 - (pos 110 , len 72) 
This log message has multiple 
lines with 
2015-03-03 
a date in it. 

-------------- 

** Grp 0 - (pos 182 , len 97) 
2015-03-03 19:32:50.1106|INFO|MyApp|This log message has 
multiple lines 
but just text only. 


** Grp 1 - (pos 218 , len 61) 
This log message has 
multiple lines 
but just text only. 

-------------- 

** Grp 0 - (pos 279 , len 186) 
2015-03-03 19:33:20.2683|ERROR|MyApp|This log message has multiple lines but 
also some confusing text like 
2015-03-03 19:33:20.2683|ERROR| which should 
still be a valid log message. 

** Grp 1 - (pos 316 , len 149) 
This log message has multiple lines but 
also some confusing text like 
2015-03-03 19:33:20.2683|ERROR| which should 
still be a valid log message. 
+0

Спасибо за ваш ответ, я вижу, что этот тоже работает. –

Смежные вопросы