使用正则表达式解析多行日志条目
Parse multiline log entries using a regex
我正在尝试使用此正则表达式解析 C# 应用程序中的日志条目:(^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3})(?!)
用于格式类似于 [日期(某种格式)] 的日志| [等级] | [应用名称] | [留言].
在哪里(我认为):
^
匹配一行的开头(在 regex101 上启用 /gm)
[0-9]{4}(-[0-9]{2}){2}
后跟日期的开始,例如 2015-03-03
([^|]+\|){3})
后跟日期的其余部分、日志级别和应用程序名称
(?!)
后跟 而不是 新日志条目的开始(应该是消息)
例如,我有以下 4 个日志条目(以换行符分隔以便说明):
2015-03-03 19:30:47.2725|INFO|MyApp|这是单行日志消息。
2015-03-03 19:31:29.1209|INFO|MyApp|此日志消息有多个
符合
2015-03-03
一个日期。
2015-03-03 19:32:50.1106|INFO|MyApp|此日志消息有
多行
但只是文字而已。
2015-03-03 19:33:20.2683|错误|MyApp|此日志消息有多行但
还有一些令人困惑的文字,比如
2015-03-03 19:33:20.2683|错误|哪个应该
仍然是有效的日志消息。
但是当我在 regex101 上测试它时,正则表达式没有捕获消息,可能是因为我不明白如何捕获负前瞻。
如果我在正则表达式中包含 .*
:
(^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3}).*(?!)
它匹配消息但只有一行(因为 .
不匹配换行符)。
那么如何捕获(多行)消息?
您使用的是什么正则表达式引擎?例如,在 Java 中有一个标志告诉“。”匹配换行符。
以下正则表达式似乎可以解决问题:
/(([0-9]{4})(-[0-9]{2}){2}([^|]+\|){3})((.(?!))*)/sg
我对您的查询所做的修改主要是一些清理(您的日期捕获组错误)。然后我添加了一个 .和 * 在最后的捕获组中。 https://regex101.com/r/fU1vV1/2
最重要的部分是 sg 标志的使用。 g 使它获得所有匹配项。 s 使它像一行一样对待它(否则你的负面前瞻永远不会起作用)。如果您可以保证注释在一行(在您的示例中是这样),那么所有这些都将是不必要的,因为您可以捕获到行尾。
您可以使用这个正则表达式:
(^\d{4}(-\d{2}){2}([^|]+\|){3})([\s\S]*?)\n*(?=^\d{4}.*?(?:[^|\n]+\|){3}|\z)
这个正则表达式也应该在 C# 中工作,只要确保使用 MULTILINE
标志。
像这样的东西应该有用。
请参阅正则表达式中的注释。
(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.
我正在尝试使用此正则表达式解析 C# 应用程序中的日志条目:(^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3})(?!)
用于格式类似于 [日期(某种格式)] 的日志| [等级] | [应用名称] | [留言].
在哪里(我认为):
^
匹配一行的开头(在 regex101 上启用 /gm)[0-9]{4}(-[0-9]{2}){2}
后跟日期的开始,例如 2015-03-03([^|]+\|){3})
后跟日期的其余部分、日志级别和应用程序名称(?!)
后跟 而不是 新日志条目的开始(应该是消息)
例如,我有以下 4 个日志条目(以换行符分隔以便说明):
2015-03-03 19:30:47.2725|INFO|MyApp|这是单行日志消息。 2015-03-03 19:31:29.1209|INFO|MyApp|此日志消息有多个 符合 2015-03-03 一个日期。 2015-03-03 19:32:50.1106|INFO|MyApp|此日志消息有 多行 但只是文字而已。 2015-03-03 19:33:20.2683|错误|MyApp|此日志消息有多行但 还有一些令人困惑的文字,比如 2015-03-03 19:33:20.2683|错误|哪个应该 仍然是有效的日志消息。
但是当我在 regex101 上测试它时,正则表达式没有捕获消息,可能是因为我不明白如何捕获负前瞻。
如果我在正则表达式中包含 .*
:
(^[0-9]{4}(-[0-9]{2}){2}([^|]+\|){3}).*(?!)
它匹配消息但只有一行(因为 .
不匹配换行符)。
那么如何捕获(多行)消息?
您使用的是什么正则表达式引擎?例如,在 Java 中有一个标志告诉“。”匹配换行符。
以下正则表达式似乎可以解决问题:
/(([0-9]{4})(-[0-9]{2}){2}([^|]+\|){3})((.(?!))*)/sg
我对您的查询所做的修改主要是一些清理(您的日期捕获组错误)。然后我添加了一个 .和 * 在最后的捕获组中。 https://regex101.com/r/fU1vV1/2
最重要的部分是 sg 标志的使用。 g 使它获得所有匹配项。 s 使它像一行一样对待它(否则你的负面前瞻永远不会起作用)。如果您可以保证注释在一行(在您的示例中是这样),那么所有这些都将是不必要的,因为您可以捕获到行尾。
您可以使用这个正则表达式:
(^\d{4}(-\d{2}){2}([^|]+\|){3})([\s\S]*?)\n*(?=^\d{4}.*?(?:[^|\n]+\|){3}|\z)
这个正则表达式也应该在 C# 中工作,只要确保使用 MULTILINE
标志。
像这样的东西应该有用。
请参阅正则表达式中的注释。
(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.