簡體   English   中英

正則表達式分析日志文件(多行)

[英]Regex to analyse log file (multiline)

我需要分析由第三方工具創建的結果文件。 因此,我嘗試創建一個小的c#工具,該工具應加載文件內容並執行正則表達式。 內容如下所示:

[1] <Download> 13.01.2016 15:16:47
[ 

Name: foobar.tif

Status:              0 (ok)
]

[2] <Download> 13.01.2016 15:17:50
[
Name: foobar2.tif

Error: 7100: No file found!

]

[3] <Upload> 13.01.2016 15:17:53
[

Name: Company.tif

Size: 3476
Error: 7200: Unauthorized!

]

...

我試圖創建一個正則表達式模式,以匹配這種類型的內容。 在此示例中,3個匹配項包括我需要檢查的4個組(索引1、2或3;任務下載/上傳,文件名以及狀態或錯誤的值)。 時間戳或可選的“大小”屬性之類的所有其他信息都可以忽略。

這是我想出的:

(?<Index>\[[0-9]+\]) (?<TaskName><[\w]+>)

但是現在這僅與索引和任務名稱匹配,我不確定如何繼續獲取“名稱”和“狀態”或“錯誤”值,因為它們在另一行中。

編輯:

好的,我嘗試通過您的回復進行操作,到目前為止,我的想法是:

\[(?<Index>[0-9]+?)\]\s<(?<Task>\w+?)>.+\n+\[[\s.]+Name\:\s(?<Name>.+)(?<Content>[\s\S]+?)\]

現在,我得到了索引,任務名稱和名稱。 到目前為止,方法還可以嗎? 接下來,我還將嘗試將錯誤/狀態歸為一組。

默認情況下,正則表達式模式始終跨多行捕獲。 可以覆蓋該行為,但是如果您要這樣做,則無需做任何特殊操作即可使其跨多行捕獲。 但是,有些字符類會考慮換行符。 最值得注意的是. 字符類匹配換行符以外的所有字符。 因此,如果要捕獲包括換行符在內的任何字符,則不能僅使用.*因為這將一直匹配到當前行的末尾。

您可以使用(.|\\n)*但是,如果可能的話,最好使用否定的字符類。 例如,如果需要在以下示例中獲取括號內的值:

 [Value One] some
 random

 data
 [Value Two]

您可以使用(\\[(?<value>[^]]*)\\][^[]*)* 請注意, [^]]*用作方括號內的值的模式, [^[]*用作方括號內的所有值的模式。 否定的字符類僅表示它與列表中沒有的任何字符匹配。 例如[^abc]將匹配不是abc任何字符。 因此, [^[]僅表示不是方括號的任何字符。 由於換行符不是方括號,因此它將與換行符以及任何其他種類的字符匹配。

我說否定的字符類優於(.|\\n)*原因是因為,為了使用(.|\\n)* ,您必須使*重復是惰性的(例如(.|\\n)*?\\[ )。 懶惰(即不貪心)重復會導致大量回溯,因此會損害性能。 因此,最好盡可能使用否定的字符類代替延遲重復。

您可以在一個正則表達式中完成所有工作,但是我認為編寫和管理它非常困難。 我可以建議將其拆分為兩個不同的正則表達式嗎? 您可以使用此索引來獲取索引,“下載/上傳”字段以及不同組中的描述:

\[([1-9]+?)\]\s<\w+?>.+\n\[([\s\S]+?)\]

然后,您可以獲取包含消息的組並將其應用於此正則表達式:

Name:\s(.+?)\n[\s\S]*?(Error:|Status:)\s+?(.+?)$

在使用上述正則表達式之前,請確保在包含消息的字符串上使用Trim(),否則該正則表達式可能無法正常工作。

這是一些使用正則表達式的C#代碼:

Regex regex1 = new Regex("\\[([1-9]+?)\\]\\s<\\w+?>.+\\n\\[([\\s\\S]+?)\\]");
            MatchCollection matches = regex1.Matches(logMessage);

            foreach (Match match in matches)
            {
                String indexField = match.Groups[1].Value;
                String message = match.Groups[2].Value.Trim();
                if (String.IsNullOrEmpty(message) == false)
                {
                    Regex regex2 = new Regex("Name:\\s(.+?)\\n[\\s\\S]*?(Error:|Status:)\\s+?(.+?)$");
                    Match messageMatch = regex2.Match(message);
                    String name = messageMatch.Groups[1].Value.Trim();
                    String statusError = messageMatch.Groups[3].Value.Trim();
                }
            }

你可能想出某事。 像下面的正則表達式在自由模式下一樣:

~
\[(?<index>\d+)\]\s*
<(?<task>\w+)>(?s).*?
\[(?s).*?
Name:\s*(?<filename>[^\n]+)(?s).*?
(?:Status|Error):\s*(?<status>\d+)(?s).*?
\]
~

暫無
暫無

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

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