[英]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]
将匹配不是a
, b
或c
任何字符。 因此, [^[]
仅表示不是方括号的任何字符。 由于换行符不是方括号,因此它将与换行符以及任何其他种类的字符匹配。
我说否定的字符类优于(.|\\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.