5

我有一个格式如下的字符串。(我添加了标记以使换行符正确显示)

-- START BELOW THIS LINE --
2013-08-28 00:00:00 - Tom Smith (Work notes)
Blah blah

b;lah blah

2013-08-27 00:00:00 - Tom Smith (Work notes)
ZXcZXCZXCZX
ZXcZXCZX
ZXCZXcZXc
ZXCZXC


-- END ABOVE THIS LINE --

我正在尝试获取一个正则表达式,它允许我从字符串的两个单独部分中提取信息。

以下表达式成功匹配第一部分:

^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) - (.*) \\(Work notes\\)\n([\\w\\W]*)(?=\n\n\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} - .* \\(Work notes\\)\n)

我试图找出一种方法来修改它以获取字符串的第二部分。我已经尝试过类似下面的内容,但最终将匹配一直延伸到字符串的末尾。就像它优先考虑 OR 后面的表达式一样。

^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) - (.*) \\(Work notes\\)\n([\\w\\W]*)(?:(?=\n\n\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} - .* \\(Work notes\\)\n)|\n\\Z)

任何帮助,将不胜感激

- 编辑 -

这是我创建的测试程序的副本,以尝试使其正确。在这种情况下,我还添加了第三条消息,上面的 RegEx 会中断。

using System;
using System.Text.RegularExpressions;

namespace RegExTest
{
  class MainClass
  {
    public static void Main (string[] args)
    {
      string str = "2013-08-28 10:50:13 - Tom Smith (Work notes)\nWhat's up? \nHow you been?\n\n2013-08-19 10:21:03 - Tom Smith (Work notes)\nWork Notes\n\n2013-08-19 10:10:48 - Tom Smith (Work notes)\nGood day\n\n";
      var regex = new Regex ("^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) - (.*) \\(Work notes\\)\n([\\w\\W]*)\n\n(?=\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} - .* \\(Work notes\\)\n)",RegexOptions.Multiline);

      foreach (Match match in regex.Matches(str))
      {
        if (match.Success)
        {
          for (var i = 0; i < match.Groups.Count; i++)
          {
            Console.WriteLine('>'+match.Groups [i].Value);
          }
        }
      }

      Console.ReadKey();
    }
  }
}

- 编辑 -

为了清楚起见,我试图提取的数据是日期和时间戳(作为一个项目)、名称和每个“段落”的“正文”。

4

3 回答 3

0

我能够使表达式起作用,但我猜它看起来有点吓人:

@"([0-9\s:-]+)(?>\s-\s)(?>[^\n\r]+[\r\n]*)((?=[^0-9]+(\d{4}-\d{2}-\d{2}|$))[\s\S])+"

@表达式之前使其成为逐字字符串,因此您不必双重转义所有内容。

注意:这绝不是正确的方法,但我还是想尝试一下。

于 2013-08-28T15:35:48.240 回答
0

正则表达式并不是真正正确的解决方案,但如果你必须......

您的问题是正则表达式贪婪和用 ^ 开始匹配的组合。如果它以 ^ 开头,它需要它来启动字符串,并且它不会匹配其他任何地方。

.*可以通过制作它来解决贪婪的问题.*?

尝试这个:

(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) - (.*?) \(Work notes\)\n([\w\W]*?)((?=\n\n\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - .*? \(Work notes\)\n)|((\s{0,})$))
于 2013-08-28T14:56:34.753 回答
0

这是你在这里得到的一个非常强大的正则表达式。

虽然您可以在多行上执行正则表达式,但这只会使事情复杂化。此外,因为您有重复的模式,所以将字符串拆分为换行符会更干净,然后只匹配每一行。

最终,如果您打算从文件中提取它,匹配文件的每一行将很容易,而不是读取整个文件然后匹配。

这是我要做的:

var regex = new Regex ("(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) - (.*?) \\(Work notes\\)");

var lines = str.split(new char[] {'\n'});

foreach (var line in lines)
{
  var match = regex.Match(line);

  if (match.Success)
  {
    for (var i = 0; i < match.Groups.Count; i++)
    {
      Console.WriteLine('>' + match.Groups[i].Value);
    }

    // will preface the body after each header
    Console.WriteLine(">");
  }
  else
  {
    Console.WriteLine(line);
  }
}

就您的正则表达式而言,我维护了您拥有的原始组,因此我们在一组中获取日期/时间戳,在另一组中获取名称。正文不会与组匹配,但构造一个作为正文的字符串将是微不足道的。

  1. (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})匹配组 1。

  2. -匹配,但未分组。

  3. (.*?)匹配组 2。

  4. \(Work notes\)匹配,但未分组。

于 2013-08-28T15:30:08.207 回答