为什么我的reg ex无法捕获第二行和后续行?

时间:2018-10-28 14:29:09

标签: c# .net regex match

更新

我尝试将RegexOptions.Singleline添加到我的regex选项中。它的工作原理是捕获了以前未捕获的行,但将整个文本文件置于第一个匹配项中,而不是根据需要在每个日期创建一个匹配项。

更新结束

更新#2

添加了使用Poul Bak的修改时显示匹配和分组的新输出。请参见下面标题为 Poul Bak修改后的输出

的屏幕截图

更新#2结束

最终更新

将目标框架从4.6.1更新到4.7.1,并对Poul Bak的reg ex进行一些调整,从而解决了所有问题。请参阅下面的Poul Bak的答案

最终更新结束

原始问题:背景

我有以下文本文件test_text.txt

2018-10-16 12:00:01 - Error 1<CR><LF>
   Error 1 text line 1<CR><LF>
   Error 1 text line 2<CR><LF>
2018-10-16 12:00:02 AM - Error 2<CR><LF>
   Error 2 text line 1<CR><LF>
   Error 2 text line 2<CR><LF>
   Error 2 text line 3<CR><LF>
   Error 2 text line 4<CR><LF>
2018-10-16 12:00:03 PM - Error 3

客观

我的目标是使每个匹配项由3个named组组成:日期,日期和文本,如下所示。

注意:撇号仅用于表示匹配文本的限制。

我希望看到的比赛:

Match 1: '2018-10-16 12:00:01 - Error 1<CR><LF>'
   Date group = '2018-10-16 12:00:01'
   Delim group = ' - '
   Text group = 'Error 1<CR><LF>Error 1 text line 1<CR><LF>Error 1 text line 2<CR><LF>'

Match 2: '2018-10-16 12:00:02 AM - Error 2<CR><LF>'
   Date group = '2018-10-16 12:00:02 AM'
   Delim group = ' - '
   Text group = 'Error 2 text line 1<CR><LF>Error 2 text line 2<CR><LF>Error 2 text line 3<CR><LF>Error 2 text line 4<CR><LF>'

Match 3: `2018-10-16 12:00:03 PM - Error 3`
   Date group = '2018-10-16 12:00:03 PM'
   Delim group = ' - '
   Text group = 'Error 3'

问题

我的正则表达式在第二行及后续文本行(例如,“错误1文本行1”,“错误2文本行1”)中无法正常工作。我希望它们会被捕获,因为我正在使用Multiline选项。

如何修改我的正则表达式以捕获第二行和第二行文本?

当前代码

using System;
using System.Text.RegularExpressions;

namespace ConsoleApp_RegEx
{
    class Program
    {
        static void Main(string[] args)
        {

            string text = System.IO.File.ReadAllText(@"C:\Users\bill\Desktop\test_text.txt");
            string pattern = @"(?<Date>\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.*)(?<Delim>\s-\s)(?<Text>.*\n|.*)";

            RegexOptions regexOptions = (RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
            Regex rx = new Regex(pattern, regexOptions);
            MatchCollection ms = rx.Matches(text);

            // Find matches.
            MatchCollection matches = rx.Matches(text);

            Console.WriteLine("Input Text\n--------------------\n{0}\n--------------------\n", text);

            // Report the number of matches found.
            Console.WriteLine("Output ({0} matches found)\n--------------------\n", matches.Count);

            int m = 1;

            // Report on each match.
            foreach (Match match in matches)
            {
                Console.WriteLine("Match #{0}: ", m++, match.Value);

                int g = 1;
                GroupCollection groups = match.Groups;

                foreach (Group group in groups)
                {
                    Console.WriteLine("   Group #{0} {1}", g++, group.Value);
                }

                Console.WriteLine();
            }

            Console.Read();
        }
    }
}

当前输出

enter image description here

Poul Bak修改的输出(在正确的轨道上,但尚不完全正确)

@"(?<Date>\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}(?:\s\w\w)?)(?<Delim>\s-\s)(?<Text>([\s\S](?!\d{4}))*)"

enter image description here

1 个答案:

答案 0 :(得分:1)

您可以使用从您修改的以下正则表达式:

@"(?<Date>\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}(?:\s\w\w)?)(?<Delim>\s-\s)(?<Text>([\s\S](?!\d{4}))*)"

我更改了'Date'组,以便它接受'AM''PM'(否则它将只与第一个匹配)。

然后,我更改了'Text'组,因此它匹配任何数量的任何字符(包括换行符),直到looks forward为止并找到新日期。

修改

我不明白,当您说'AM''PM'不匹配时,它们是'Date'组的一部分。我假设您希望它们成为'Delim'组的一部分,所以我已将支票移至该组。

我也已将网上论坛更改为非捕获网上论坛。

新正则表达式:

 @"(?<Date>\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2})(?<Delim>(?:\s\w\w)?\s-\s)(?<Text>(?:[\s\S](?!\d{4}))*)"

顺便说一句:您应该更改用于检查组的代码,如下所示:

        foreach (Group group in groups)
        {
            Console.WriteLine("   Group #{0} {1}", group.Name, group.Value);
        }

然后您将看到named GroupsName旁的Value。为组命名后,无需按索引访问。

修改 2:

关于“ group.Name”:我误用了“ Group”(大写),应该是:“ group.Name”。

这是正则表达式现在的样子:

@"(?<Date>\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}(?:\s\w\w)?)(?<Delim>\s-\s)(?<Text>(?:[\s\S](?!\d{4}))*)"

我建议您设置'RegexOptions.ExplicitCapture'标志,然后仅获取命名组。