You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用正则表达式从日志文件中提取指定字段内容?

解决TLWin Session Data Log日志字段提取的正则问题

我明白你现在的痛点——想用C#正则从TLWin日志里抓13个指定字段存数据库,但写的正则要么匹配不全,要么分组引用出错。咱们来一步步解决这个问题。

先明确目标字段(带示例)

  • Date Logged: 09-29-2014
  • Task Name: XXXXXX_A06_U1
  • Machine ID: 123456789
  • Device: WINBOND_ELECTRONICS W25Q64FV-SS-Q SO8
  • Devices Total: 1105
  • Devices Passed: 1104
  • Devices Failed: 1
  • Overall Device Yield: 99.91%
  • Nominal Throughput: 666
  • Job Throughput: 290
  • Devices Picked Input: 1110
  • Devices Failed Vision: 0
  • Devices Failed REST: 0

你当前代码的核心问题

  1. 正则分支逻辑错误:你用|把多个字段的匹配规则分开,正则引擎只会匹配第一个符合的分支,其他字段根本不会被捕获,导致大部分分组是空值。
  2. 冗余的文本替换:你把换行、制表符换成空格,但又用原始文本去匹配,既没用到处理后的文本,还破坏了日志的行结构(本来每个字段是单独一行的)。
  3. 分组索引不匹配:你的正则只定义了4个捕获组,但代码里直接访问Groups[5]Groups[6],这肯定会报错,因为这些分组根本不存在。

修正后的代码方案

我建议用命名捕获组来写正则,这样不用记分组索引,可读性和维护性都强很多,而且确保所有字段都能被匹配到(假设日志里字段的顺序和你给出的一致):

using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Configuration;

// ... 其他业务代码 ...

foreach (string file in Directory.EnumerateFiles(ConfigurationManager.AppSettings["Path"], "*.log"))
{
    string fileText = File.ReadAllText(file);
    
    // 构建匹配所有字段的正则,用命名捕获组,忽略模式里的空格(方便排版),支持多行匹配
    var logRegex = new Regex(
        @"Date\sLogged\s*:\s*(?<DateLogged>[\d\-]+)\s*
          Task\sName\s*:\s*(?<TaskName>.+?)\s*
          Machine\sID\s*:\s*(?<MachineID>\d+)\s*
          Device\s*:\s*(?<Device>.+?)\s*
          Devices Total\s*:\s*(?<DevicesTotal>\d+)\s*
          Devices Passed\s*:\s*(?<DevicesPassed>\d+)\s*
          Devices Failed\s*:\s*(?<DevicesFailed>\d+)\s*
          Overall Device Yield\s*:\s*(?<OverallYield>[\d\.%]+)\s*
          Nominal Throughput\s*:\s*(?<NominalThroughput>\d+)\s*
          Job Throughput\s*:\s*(?<JobThroughput>\d+)\s*
          Devices Picked Input\s*:\s*(?<DevicesPickedInput>\d+)\s*
          Devices Failed Vision\s*:\s*(?<DevicesFailedVision>\d+)\s*
          Devices Failed REST\s*:\s*(?<DevicesFailedREST>\d+)",
        RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

    var match = logRegex.Match(fileText);
    
    if (match.Success)
    {
        // 从命名捕获组取值,不用担心索引搞错
        DateTime dtLogged = DateTime.ParseExact(match.Groups["DateLogged"].Value, "MM-dd-yyyy", CultureInfo.InvariantCulture);
        string taskName = match.Groups["TaskName"].Value.Trim();
        string machineId = match.Groups["MachineID"].Value;
        string icDevice = match.Groups["Device"].Value.Trim();
        int deviceTotal = int.Parse(match.Groups["DevicesTotal"].Value);
        int devicePassed = int.Parse(match.Groups["DevicesPassed"].Value);
        int deviceFailed = int.Parse(match.Groups["DevicesFailed"].Value);
        string overallYield = match.Groups["OverallYield"].Value;
        int nominalThroughput = int.Parse(match.Groups["NominalThroughput"].Value);
        int jobThroughput = int.Parse(match.Groups["JobThroughput"].Value);
        int devicesPickedInput = int.Parse(match.Groups["DevicesPickedInput"].Value);
        int devicesFailedVision = int.Parse(match.Groups["DevicesFailedVision"].Value);
        int devicesFailedREST = int.Parse(match.Groups["DevicesFailedREST"].Value);
        
        // 这里调用你的SQL存储过程,把这些参数传进去即可
    }
}

额外优化点

  • 日期解析用ParseExact指定格式(MM-dd-yyyy),避免因系统区域设置不同导致解析失败。
  • 对字符串字段调用Trim(),去掉可能存在的首尾空格。
  • 如果日志里字段顺序不固定,那可以把每个字段的正则单独写,逐个匹配,比如:
    // 单独匹配每个字段的示例
    var dateMatch = Regex.Match(fileText, @"Date\sLogged\s*:\s*([\d\-]+)");
    string dateLogged = dateMatch.Success ? dateMatch.Groups[1].Value : string.Empty;
    

这样调整后,应该就能正确捕获所有目标字段了。

内容的提问来源于stack exchange,提问作者Everton Wcks

火山引擎 最新活动