我试图在C#应用程序中使用正则表达式拆分包含自由格式文本的数据库字段。添加的评论只是在最后添加了一条评论。这是样本格式:
Bob Smith [21-Mar-2013 10:46:02 AM]: this that and the other thing
followed by some linefeeds and somesuch
Alexey Jones [08-Jul-2013 1:44:59 PM]: and here is some other comment that I, Alexey deemed worthy to put into the system
I also like using the enter key
Kim Katillicus [09-Jun-2014 2:34:43 PM]: Don't forget about my comments
意图是Alexey希望看到他的评论的输出,而不是其他人的评论(这将输出到静态报告)。我正在尝试使用以下正则表达式模式的变体来恢复匹配集合:
^(.*\[\d{2}-\w{3}-\d{4}.*(AM|PM)\]:\s[\s\S]*)*
我只能得到一个包含所有内容的大blob或者每个人条目的第一行单独匹配。我正在寻找帮助修复这种模式。不确定我是否接近我所拥有的,或者正在咆哮错误的树。
注意:我正在使用Expresso测试我的表达式。目前我检查了多线开关。
答案 0 :(得分:0)
问题在于这一部分:
[\s\S]*
其中说“匹配任何是或不是空白0或更多次”。这将完全包括表达式开始第一次出现后的所有内容。
在我看来,答案需要的逻辑比用单个正则表达式表达的逻辑要多。例如,正如@evanmcdonnal指出的那样,您可以拆分换行符,然后将每行与您的前导码RegEx匹配,将行合并为单个注释直到下一个匹配。这是一个C#方法:
public static class CommentsExtractor
{
private static Regex preambleExpression =
new Regex(@"^.*\[\d{2}-\w{3}-\d{4}.*(AM|PM)\]:\s");
public static List<string> CommentsFromText(string text)
{
var comments = new List<string>();
var lines = text.Split(new char[]{'\n', '\r'},
StringSplitOptions.RemoveEmptyEntries);
var currentComment = new StringBuilder();
bool anyMatches = false;
foreach (var line in lines)
{
var match = preambleExpression.Match(line);
// If we see a new preamble, it's time to push
// the current comment into the list.
// However, the first time through, we don't have
// any data, so we'll skip it.
if(match.Success)
{
if (anyMatches)
{
comments.Add(currentComment.ToString());
currentComment.Clear();
}
anyMatches = true;
}
currentComment.AppendLine(line);
}
// Now we need to push the last comment
comments.Add(currentComment.ToString());
return comments;
}
}
Github上提供了一个工作示例WPF应用程序。