我有一个以下格式的字符串。 (我添加了标记以使新线正确显示)
-- 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)
任何帮助将不胜感激
- 编辑 -
这是我创建的测试程序的副本,试图让这个更正确。在这种情况下,我还添加了第3条消息,上面的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();
}
}
}
- 编辑 -
为了说清楚,我试图提取的数据是日期和时间戳(作为一个项目),名称和每个“段落”中的“正文”。
答案 0 :(得分: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,})$))
答案 1 :(得分: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);
}
}
就你的正则表达式而言,我保留了原来的组,所以我们在一组中得到日期/时间戳,在另一组中得到名字。身体不会与一个组匹配,但构造一个身体的字符串将是微不足道的。
(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})
匹配组1。
-
已匹配但未分组。
(.*?)
匹配组2。
\(Work notes\)
已匹配但未分组。
答案 2 :(得分:0)
我能够得到一个表达式但我觉得它看起来有点可怕:
@"([0-9\s:-]+)(?>\s-\s)(?>[^\n\r]+[\r\n]*)((?=[^0-9]+(\d{4}-\d{2}-\d{2}|$))[\s\S])+"
表达式之前的@
使其成为逐字字符串,这样您就不必双重转义所有内容。
注意:这绝对不是正确的方法,但我想尝试一下。