簡體   English   中英

使用正則表達式解析日志文件

[英]Parsing a log file with regular expressions

我目前正在為內部日志文件(由log4php,log4net和log4j生成)解析器。 到目前為止,我有一個很好的正則表達式來解析日志,除了一個令人討厭的地方:一些日志消息跨越多行,我無法正確匹配。 我現在使用的正則表達式是這樣的:

(?<date>\d{2}/\d{2}/\d{2})\s(?<time>\d{2}):\d{2}:\d{2}),\d{3})\s(?<message>.+)

日志格式(我用於測試解析器的格式)是這樣的:

07/23/08 14:17:31,321 log 
message
spanning
multiple
lines
07/23/08 14:17:31,321 log message on one line

當我現在運行解析器時,我只會看到日志開始的那一行。 如果我將其更改為跨越多行,則只會得到一個結果(整個日志文件)。


@samjudson:

您需要將RegexOptions.Singleline標志傳遞到正則表達式中,以便使用“。”。 匹配所有字符,不僅匹配換行以外的所有字符(這是默認值)。

我試過了,但隨后它匹配了整個文件。 我還嘗試將消息組設置為。+? (非貪婪),但隨后它匹配一個字符(這不是我要找的字符)。

問題在於消息的模式在日期組上也匹配,因此當它在換行符上不中斷時,它會不斷地不斷變化。


我現在將此正則表達式用於消息組。 除非日志消息中有與日志消息開頭相同的模式,否則它會起作用。

(?<message>(.(?!\d{2}/\d{2}/\d{2}\s\d{2}:\d{2}:\d{2},\d{3}\s\[\d{4}\]))+)

僅當日志消息在行首不包含日期時,此方法才有效,但是您可以嘗試在“消息”組中為日期添加否定的前瞻斷言:

(?<date>\d{2}/\d{2}/\d{2})\s(?<time>\d{2}:\d{2}:\d{2},\d{3})\s(?<message>(.(?!^\d{2}/\d{2}/
\d{2}))+)

請注意,這需要使用RegexOptions.MultiLine標志。

您顯然需要將“消息行”與“日志行”區分開來; 如果您允許消息部分以換行后的日期/時間開頭,則根本無法確定消息的一部分,什么不是。 因此,不需要使用點,而是需要一個表達式,該表達式允許所有不包含換行符后跟日期和時間的內容。

但是,就我個人而言,我不會使用正則表達式來解析整個日志條目。 我更喜歡使用自己的循環遍歷每一行,並使用一個簡單的正則表達式來確定行是否是新條目的開始。 從可讀性的角度來看,這也是我的偏愛。

您遇到的問題是您需要終止RegEx模式,以便它知道一條消息何時結束然后下一條開始。

在默認模式下運行時,換行符用作隱式終止符。

問題是,如果進入多行模式,則沒有終結符,因此模式會吞噬整個文件。 非貪心匹配的字符越少越好。

現在,如果使用下一條消息的日期作為終止符,我認為您的解析器將僅獲得每隔一行。

文件中還有其他內容可以終止模式嗎?

您需要傳遞RegexOptions 在單行標志中加入正則表達式,使之為“。”。 匹配所有字符,不僅匹配換行以外的所有字符(這是默認值)。

您可能會發現,使用適當的解析器生成器來解析文件要容易得多-ANTLR可以在C#中生成一個解析器。上下文自由解析器只有在您“獲取”它們之后才看起來很困難-之后,它們使用起來更簡單,更友好比正則表達式...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM