我在日志文件中有以下数据,我想提取在"处理开始"的两个短语之间的行。和"流程已完成"包括线的开始和线的结束。
2016-11-28 12:18:59.5286 | 14 | Info | Process Started -ABC *****
....
..
2016-11-28 12:18:59.5286 | 14 | Info | Process Completed -ABC, Status: Failed***
2016-11-28 13:18:59.5286 | 14 | Info | Process Started -DEF
....
..
2016-11-28 13:18:59.5286 | 14 | Info | Process Completed -DEF Status: Passed***
使用以下RegEx我能够提取行,但缺少给定匹配的行的开头和结尾。
Regex r = new Regex("^*?Process Started -"+process.Name+"(.*?)Process Completed: "+process.Name+".*?", RegexOptions.Singleline);
以上正则表达式返回
Process Started -ABC *****
....
..
2016-11-28 12:18:59.5286 | 14 | Info | Process Completed
但我需要这样
2016-11-28 12:18:59.5286 | 14 | Info | Process Started -ABC *****
....
..
2016-11-28 12:18:59.5286 | 14 | Info | Process Completed -ABC, Status: Failed***
答案 0 :(得分:2)
你很接近,但最后的懒惰量词就是问题:它将匹配最少的东西,在这种情况下什么都不是。
以下是正则表达式的修订版:
Regex r = new Regex("[^\n]*?Process Started -"
+ process.Name + "(.*?)Process Completed -"
+ process.Name + "[^\n]*", RegexOptions.Singleline);
我所做的改变:
[^\n]*
在开头和结尾都会阻止匹配换行符,但会获得其余部分额外信息:
我不确定您打算如何在代码的上下文中使用它,但如果您需要提取所有这些部分,而不是一个特定的进程名称,您可以使用此变体一次性获取所有这些部分:
Regex r = new Regex("[^\n]*?Process Started -(\w+)(.*?)Process Completed -\1[^\n]*", RegexOptions.Singleline);
\1
是对(\w+)
匹配的任何进程名称的反向引用。最终会得到一组匹配项,每个过程名称都有一个。
答案 1 :(得分:0)
您需要使用Multiline
选项,然后您可以执行以下操作:
var reg = new Regex(@"^.*Process Started -ABC(.*)$(\n^.*$)*?\n(^.*Process Completed -ABC.*)$",
RegexOptions.Multiline);
但它有点难看。正如@ blaze_125在评论中建议的那样,你最好的选择是分成行并迭代寻找Started
和Completed
字符串,然后抓住其间的所有行
您可以执行以下操作:
var lines = str.Split('\n');
var q = new Queue<string>();
foreach (var l in lines)
{
q.Enqueue(l);
if (l.Contains("Process Completed")) // you could use a regex here if you want more
// complex matching
{
string output;
while (q.Count > 0)
{
// your queue here would contain exactly one entry
output = q.Dequeue();
Console.WriteLine(output);
}
}
}