使用正则表达式解析多行日志条目

时间:2015-03-04 20:14:58

标签: c# .net regex negative-lookahead

我正在尝试使用此正则表达式解析C#应用程序中的日志条目:(^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3})(?!\1)以及 [日期(某种格式)] |格式的日志 [等级] | [appname] | [消息]

在哪里(我认为):

  • ^匹配一行的开头(在regex101上启用 / gm
  • [0-9]{4}(-[0-9]{2}){2}后面是2015-03-03的日期开始
  • ([^|]+\|){3})后跟剩余的日期,日志级别和应用名称
  • (?!\1)后跟新日志条目的开头(应该是消息)

例如,我有以下 4 日志条目(由换行符分隔以便澄清):

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)它与消息匹配但只有一行(因为.与换行符不匹配)。

那么如何捕获(多行)消息?

3 个答案:

答案 0 :(得分:3)

您可以使用此正则表达式:

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

RegEx Demo

这个正则表达式也适用于C#,只需确保使用MULTILINE标志。

答案 1 :(得分:3)

这样的事情应该有效 请参阅正则表达式中的注释 ( mod :为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.

答案 2 :(得分:-2)

你使用什么正则表达式引擎?例如,在Java中,有一个标志可以告诉"。"匹配换行符。

以下正则表达似乎可以解决问题:

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

我对您的查询所做的修改主要是一些清理(您的日期捕获组错误)。然后我加了一个。和*在最后的捕获组中。 https://regex101.com/r/fU1vV1/2

最重要的部分是使用sg标志。 g让它获得所有比赛。 s使它像一条线一样对待它(否则你的负面前瞻永远不会起作用)。如果您可以保证评论在一行(他们在您的示例中),所有这些都是不必要的,因为您可以捕获到该行的末尾。