【发布时间】:2018-10-29 18:31:01
【问题描述】:
我正在尝试使用Regex 在段落中搜索某些文本。我希望现实主义者在前后返回 X 个单词,并在所有出现的文本周围添加高亮显示。
例如: 考虑以下段落。结果前后应至少有 10 个字符,并且没有单词被截断。搜索词是“狗”。
狗是一种宠物。它是最听话的动物之一。那里 世界上有很多种狗。其中一些非常友好 而其中一些是危险的。狗有不同的颜色,比如 黑色、红色、白色和棕色。有些老人的皮肤滑溜溜的 有些皮肤粗糙。狗是肉食性动物。他们喜欢 吃肉。它们有四条腿、两只耳朵和一条尾巴。狗是 受过训练以执行不同的任务。他们保护我们免受小偷 b) 守卫我们的房子。他们是充满爱的动物。狗叫人的 最好的朋友。他们被警察用来寻找隐藏的东西。他们 是世界上最有用的动物之一。狗哥尼特!
我想要的结果是一个如下所示的数组:
- 狗是宠物
- 世界上有很多种狗
- 危险。 狗是不同的
- 皮肤粗糙。 狗是肉食性的
- 还有一条尾巴。 狗经过训练
- 动物。 狗被称为
- 世界。 狗gonit!
我有什么:
我四处搜索,发现以下正则表达式完美地返回了所需的结果,但没有添加额外的格式。我创建了几种方法来促进每个功能:
private List<List<string>> Search(string text, string searchTerm, bool searchEntireWord) {
var result = new List<List<string>>();
var searchTerms = searchTerm.Split(' ');
foreach (var word in searchTerms) {
var searchResults = ExtractParagraph(text, word, sizeOfResult, searchEntireWord);
result.Add(searchResults);
if (searchResults.Count > 0) {
foreach (var searchResult in searchResults) {
Response.Write("<strong>Result:</strong> " + searchResult + "<br>");
}
}
}
return result;
}
private List<string> ExtractParagraph(string text, string searchTerm, sizeOfResult, bool searchEntireWord) {
var result = new List<string>();
searchTerm = searchEntireWord ? @"\b" + searchTerm + @"\b" : searchTerm;
//var expression = @"((^.{0,30}|\w*.{30})\b" + searchTerm + @"\b(.{30}\w*|.{0,30}$))";
var expression = @"((^.{0," + sizeOfResult + @"}|\w*.{" + sizeOfResult + @"})" + searchTerm + @"(.{" + sizeOfResult + @"}\w*|.{0," + sizeOfResult + @"}$))";
var wordMatch = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline);
foreach (Match m in wordMatch.Matches(text)) {
result.Add(m.Value);
}
return result;
}
我可以这样称呼它:
var text = "The Dog is a pet animal. It is one of...";
var searchResults = Search(text, "dog", 10);
if (searchResults.Count > 0) {
foreach (var searchResult in searchResults) {
foreach (var result in searchResult) {
Response.Write("<strong>Result:</strong> " + result + "<br>");
}
}
}
我还不知道在 10 个字符中多次出现该词的结果或如何处理。即:如果一个句子有“狗当然是狗!”。我想我可以稍后再处理。
测试:
var searchResults = Search(text, "dog", 0, false); // should include only the matched word
var searchResults = Search(text, "dog", 1, false); // should include the matched word and only one word preceding and following the matched word (if any)
var searchResults = Search(text, "dog", 10, false); // should include the matched word and up to 10 characters (but not cutting off words in the middle) preceding and following it (if any)
var searchResults = Search(text, "dog", 50, false); // should include the matched word and up to 50 characters (but not cutting off words in the middle) preceding and following it (if any)
问题:
我创建的函数允许搜索将 searchTerm 仅作为整个单词或单词的一部分来查找。
我所做的是在显示结果时对结果进行简单的Replace(word, "<strong>" + word "</strong>")。如果我正在搜索单词的一部分,这非常有用。但是在搜索整个单词时,如果结果中包含 searchTerm 作为单词的一部分,则该部分单词会突出显示。
例如:如果我搜索“狗”,结果是:“所有狗都去狗天堂。”突出显示为“所有狗都去狗天堂”。但我想要“所有的狗都去狗天堂。”
问题:
问题是我怎样才能让 matched 单词用一些 HTML 包裹起来,比如 <strong> 或其他任何我想要的东西?
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。
-
我认为您当前的描述需要更新。您想要 1) 提取搜索词与周围文本的所有重叠匹配项,2) 将包含词条的词/搜索词作为整个词(取决于
searchEntireWord选项)在每个匹配项中使用强标签。正确的?如果是,你可以试试this code。 -
嗨@WiktorStribiżew 实际上,我回顾了您以前的解决方案,尽管如果前一个单词有逗号或句点,它不会在搜索词之前返回字符。我做了进一步的测试,发现情况并非如此。我在聊天中添加了我当前的解决方案。您是否介意查看并根据需要进行任何更改。
-
我稍微清理了模式并修复了整个单词
expression模式。见this demo。如果它产生预期的结果,请告诉我,我会发布一个答案并解释每件事。 -
@WiktorStribiżew 到目前为止它似乎确实有效。你能解释一下你的这个片段的版本
(?<!\w)(dog)(?!\w)与我的(\w*\b)(dog)(\b\w*)有什么不同吗?