【问题标题】:Regex to match the date from string with where clause正则表达式将字符串中的日期与 where 子句匹配
【发布时间】:2019-04-01 08:49:16
【问题描述】:

我需要从下面的示例文本中获取日期字符串,即 2019-01-22 15:36:141,023,仅当行包含 Correct 而不是 >Test12 字。所以我最好在下面的字符串中得到两个匹配项(第 3 行和第 5 行)。

第 1 行:2019-01-22 15:36:141,043:[测试][123] 信息 - 测试:正确的 Test12 ping

第 2 行:2019-01-22 15:36:141,029:[测试][124323] 信息 - 测试:错误的 Test12 ping

第 3 行:2019-01-22 15:36:141,023:[测试][12554363] 信息 - 测试:正确的测试 ping

第 4 行:2019-01-22 15:36:141,123:[测试][6761213] 信息 - 测试:错误的 Test12 ping

第 5 行:2019-01-22 15:36:141,093:[测试][46543123] 信息 - 测试:测试 ping 无效

第 6 行:2019-01-22 15:36:141,890:[测试][887] 信息 - 测试:正确的测试 ping

我可以使用 (?\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2 获取日期字符串}(?:,\d{3}\b)?) 但不确定如何包含其他条件。有什么线索吗?

【问题讨论】:

  • 为什么不单独执行附加检查?这将使代码保持“干净”并且提取正则表达式更易于维护。
  • 同意维克托。但是,您可以将“正确”和“测试”附加到您当前的正则表达式。 Demo
  • 您可以使用像\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?(?=.*\r?$(?<!Test12.*)(?<=Correct.*)) 这样的正则表达式,但如果您可以访问代码,这并不是正确的方法。
  • @coder89 你没有使用多行选项,添加它,(?m)在模式的开头,或者用RegexOptions.Multiline编译
  • 如果您不需要在日期之前检查这些单词,请尝试\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?(?!.*Test12)(?=.*Correct)

标签: c# .net regex


【解决方案1】:

不增加正则表达式的额外复杂性,您可以遍历文件中的行并使用常规字符串方法检查Test12Correct

var results = new List<string>();
using (var sr = new StreamReader(filepath, true)) 
{
    var line = "";
    while ((line=sr.ReadLine()) != null)
    {
        if (line.Contains("Correct") && !line.Contains("Test12")) 
        {
            var res = Regex.Match(line, @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?");
            if (res.Success)
            {
                results.Add(res.Value);
            }
        }
    }
}

使用正则表达式,我f您要检查的单词是否出现在之后日期使用

\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?(?!.*Test12)(?=.*Correct)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^

请参阅regex demo

这里,(?!.*Test12)(?=.*Correct) 是前瞻,确保 1) 没有 Test12 和 2) 在当前位置右侧尽可能多的除换行符以外的任何 0+ 字符之后有一个子字符串 Correct (即日期之后)。

如果这些词可能出现在字符串中的任何位置,您可以使用

(?m)\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?(?=.*\r?$(?<!Test12.*)(?<=Correct.*))
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

this regex demo

这里,(?m) 选项将RegexOptions.Multiline 设置为true,以便$ 可以被解析为行锚的结尾,而(?=.*\r?$(?&lt;!Test12.*)(?&lt;=Correct.*)) 正向前瞻执行以下操作检查:它要求到行尾有 0+ 个字符,然后,在行尾,使用后向执行两个检查:负后向 (?&lt;!Test12.*) 确保没有 Test12 anywhere 在一行上,正向向后查看 (?&lt;=Correct.*) 确保有一个 Correct 子字符串 anywhere 在一行上。

$ 之前的\r? 可选CR 是必需的,因为在多行模式下$\r 之前不匹配是一个相当烦人的事实。

【讨论】:

    【解决方案2】:

    我认为您的意思是匹配第 3 行和第 6 行,因为第 5 行不包含 Correct

    要不包含“Test12”,您可以使用负前瞻。要在之后匹配“正确”,您可以在模式中匹配它并使用单词边界\b 来防止它成为更大单词的一部分。

    您的模式可能如下所示:

    ^(?!.*\bTest12\b).*?(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?).*\bCorrect\b.*$
    

    这将匹配:

    • ^ 字符串开始
    • (?!.*\bTest12\b) 断言后面的内容不包含 Test12
    • .*?匹配任何不贪心的字符
    • (\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2,}(?:,\d{3}\b)?)抓拍成组的日期样图案
    • .* 匹配任意字符 0+ 次
    • \bCorrect\b 匹配正确
    • .* 匹配任意字符 0+ 次
    • $字符串结束

    Regex demo | C# demo

    注意

    这部分(?:,\d{3}\b)? 是否也应该匹配逗号前的一个数字,例如(?:\d,\d{3}\b)? 查看示例数据?

    【讨论】:

    • 感谢@The Fourth Bird 辉煌(这是一个错字,我的意思是第 3 行和第 6 行),这给了我完整的行,如果我只需要日期字符串,即 2019-01-22 15:36: 141,023
    • 获取日期部分只有您可以使用捕获组。在模式中,将(?: 转为( 我已经更新了我的答案。
    • @coder89 这种方法有一点:Correct 必须跟在日期之后才能找到匹配项。这很可能是您需要的,但您实际上应该在问题中阐明该要求。
    • @WiktorStribiżew 你可以发布一个答案,我会投赞成票。
    • @Wikto 如果问题不清楚,我深表歉意,您的解决方案就像一个魅力。
    【解决方案3】:

    这是一种没有正则表达式的方法。日期看起来不正确。我认为逗号的位置错误,所以我修复了它。

                DateTime today = DateTime.Parse("2019-01-22 15:36:14");
                string input =
                    "2019-01-22 15:36:14,1023: [Test][123] INFORMATION - Testing: Correct Test12 ping\n" +
                    "2019-01-22 15:36:14,1023: [Test][124323] INFORMATION - Testing: Wrong Test12 ping\n" +
                    "2019-01-22 15:36:14,1023: [Test][12554363] INFORMATION - Testing: Correct Test ping\n" +
                    "2019-01-22 15:36:14,1023: [Test][6761213] INFORMATION - Testing: Wrong Test12 ping\n" +
                    "2019-01-22 15:36:14,1023: [Test][46543123] INFORMATION - Testing: Invalid Test ping\n" +
                    "2019-01-22 15:36:14,1023: [Test][887] INFORMATION - Testing: Correct Test ping";
    
                StringReader reader = new StringReader(input);
                string line = "";
    
                while ((line = reader.ReadLine()) != null)
                {
                    string[] splitDate = line.Split(new string[] { ": [Test]" }, StringSplitOptions.None);
                    DateTime date = DateTime.ParseExact(splitDate[0].Replace(",","."), "yyyy-MM-dd HH:mm:ss.FFFF", System.Globalization.CultureInfo.InvariantCulture);
                    string[] splitTest = splitDate[1].Split(new char[] { ':' });
    
                    if ((date.Date == today.Date) && splitTest[1].Contains("Correct") && !splitTest[1].Contains("Test12"))
                    {
                        Console.WriteLine(line);
                    }
                }
                Console.ReadLine();
    

    【讨论】:

      猜你喜欢
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 2019-05-01
      • 2013-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多