1

我想使用正则表达式计算“GSA 搜索”的总“经过时间”。

我的日志文件格式为:

WX Search = Server:nomos-scanner.corp.com User:vibsharm appGUID: wx Elapsed Time: 975ms SaveSearchID:361
WX Search = Server:nomos-scanner.corp.com User:vibsharm appGUID: wx Elapsed Time: 875ms SaveSearchID:361
GSA Search = Server:nomos-scanner.corp.com User:gulanand appGUID: wx Elapsed Time:890ms SaveSearchID:361
GSA Search = Server:nomos-scanner.corp.com User:vibsharm appGUID: wx Elapsed Time:887ms SaveSearchID:361
GSA Search = Server:nomos-scanner.corp.com User: gulanand appGUID: wx Elapsed Time: 875.5ms SaveSearchID:361
GSA Search = Server:nomos-scanner.corp.com User:vibsharm appGUID: wx Elapsed Time:877.6ms SaveSearchID:361

我的代码:

 string searchKeyword = "WX GSA Search";
            string fileName = @"C:\Users\karansha\Desktop\sample log.txt";
            string[] textLines = File.ReadAllLines(fileName);

            List<string> results = new List<string>();

            foreach (string line in textLines)
            {
                if (line.Contains(searchKeyword))
                {
                    results.Add(line);
                }
            }
            string x = string.Join(",", results);
            List<string> value = new List<string>();
            Regex regex = new Regex(@"Elapsed Time:\s*(?<value>\d+\.?\d*)\s*ms");
            MatchCollection matches = regex.Matches(x);
            foreach (Match match in matches)
            {
                var time = match.Groups["value"].Value;
                if (value.Contains(time)) value.Add(time);
            }
            int ElapsedTime = value.Count();
            Console.WriteLine(ElapsedTime);
            // keep screen from going away
            // when run from VS.NET
            Console.ReadLine();
4

4 回答 4

3

Linq方式:

Regex regex = new Regex(@"Elapsed Time:\s*(?<value>\d+\.?\d*)\s*ms");
double totalTime = textLines.Where(line => line.Contains(searchKeyword))
                            .Select(line => regex.Match(line))
                            .Where(match => match.Captures.Count > 0)
                            .Sum(match => Double.Parse(match.Groups["value"].Value));

非Linq方式:

Regex regex = new Regex(@"Elapsed Time:\s*(?<value>\d+\.?\d*)\s*ms");
double totalTime = 0;
int count = 0;
foreach (string line in textLines)
{
    if (line.Contains(searchKeyword))
    {
        Match match = regex.Match(line);
        if (match.Captures.Count > 0)
        {
            try
            {
                count++;
                double time = Double.Parse(match.Groups["value"].Value);
                totalTime += time;
            }
            catch (Exception)
            {
                // not a number
            }
        }
    }
}

double average = totalTime/count;
于 2013-03-04T10:57:21.693 回答
2

您可以在没有正则表达式的情况下使用 LINQ 获得总时间(因为您的日志文件具有一致的格式)。这是一个计算总时间、平均时间和最大时间的示例(如果搜索关键字没有日志项,DefaultIfEmpty将返回0 ):

string searchKeyword = "GSA Search";
var times = File.ReadAllLines("log.txt")
                .Where(l => l.Contains(searchKeyword))
                .Select(ParseElapsedTime)
                .DefaultIfEmpty() 
                .ToList();

 var averageTime = times.Average();   // 882,525
 var maxTime = times.Max();           // 890
 var totalTime = times.Sum();         // 3530,1

我建议您使用单独的方法从日志行解析经过的时间。这将使代码更易于维护:

private static double ParseElapsedTime(string logLine)
{
    var startIndex = logLine.IndexOf("Elapsed Time:") + "Elapsed Time:".Length;
    var endIndex = logLine.IndexOf("ms", startIndex);
    var s = logLine.Substring(startIndex, endIndex - startIndex).Trim();
    return Double.Parse(s, CultureInfo.InvariantCulture.NumberFormat);
}

如果性能对您不重要,您始终可以使用正则表达式来解析行 - 只需更改方法实现即可。

于 2013-03-04T11:03:53.583 回答
0

鉴于您已经使用正则表达式解析了每条记录的经过时间(以毫秒为单位) ,您可以将生成的字符串(例如877.6)转换为浮点值:

string time = "234.4";
float elapsed = Single.Parse(time, CultureInfo.InvariantCulture);

Single.Parse仅当您确定该值是有效的浮点值时才使用。否则,您应该使用Single.TryParse,但它的工作方式略有不同。

您可以使用 LINQ 从您的列表中轻松总结经过的时间values

var values = new [] { "975", "875", "890", "887", "875.5", "877.6" };
float total = arr.Sum(v => Single.Parse(v, CultureInfo.InvariantCulture));
于 2013-03-04T10:58:22.590 回答
0

这是在 Vb 中(但可以很容易地翻译成 c#)。结果,从您上面的字符串中,我得到了 5380.1 。

Dim totaltime As Decimal = 0.0'choose your data type, I prefer decimal for accuracy
'This should get in between "Time:" and "ms" 
Dim getTimesRgx As New Regex("(?<=Time:)(.*?)(?=ms)", RegexOptions.IgnoreCase)
Dim Times As MatchCollection = getTimesRgx.Matches(YourFileAsString)
If Times.Count > 0 Then
   For Each time As Match In Times
      totaltime = totaltime + Decimal.parse(time.value)
   Next
End If
于 2013-03-11T18:22:03.230 回答