什么正则表达式将匹配文本,不包括 HTML 标记中的内容?
Posted
技术标签:
【中文标题】什么正则表达式将匹配文本,不包括 HTML 标记中的内容?【英文标题】:What regex will match text excluding what lies within HTML tags? 【发布时间】:2010-09-15 20:08:01 【问题描述】:我正在为需要突出显示搜索词的搜索结果页面编写代码。这些术语恰好出现在表格单元格中(应用程序正在遍历 GridView 行单元格),并且这些表格单元格可能包含 html。
目前,我的代码如下所示(相关大块如下所示):
const string highlightPattern = @"<span class=""Highlight"">$0</span>";
DataBoundLiteralControl litCustomerComments = (DataBoundLiteralControl)e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Controls[0];
// Turn "term1 term2" into "(term1|term2)"
string spaceDelimited = txtTextFilter.Text.Trim();
string pipeDelimited = string.Join("|", spaceDelimited.Split(new[] " ", StringSplitOptions.RemoveEmptyEntries));
string searchPattern = "(" + pipeDelimited + ")";
// Highlight search terms in Customer - Comments column
e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Text = Regex.Replace(litCustomerComments.Text, searchPattern, highlightPattern, RegexOptions.IgnoreCase);
令人惊讶的是它的工作原理。但是,有时我匹配的文本是如下所示的 HTML:
<span class="CustomerName">Fred</span> was a classy individual.
如果您搜索“class”,我希望突出显示代码将“class”包装在“classy”中,但当然不是恰好在其中的 HTML 属性“class”!如果您搜索“Fred”,则应突出显示。
那么,有什么好的正则表达式可以确保匹配只发生在 html 标签之外?它不必是超级硬核。我认为只要确保匹配不在 之间就可以了。
【问题讨论】:
如果有人在您的示例中搜索 Fred,是否应该突出显示? 是的。谢谢你的慰问。好问题。我将编辑问题。 【参考方案1】:这个正则表达式应该可以完成这项工作:(?<!<[^>]*)(regex you want to check: Fred|span)
它检查从匹配字符串开始向后退的正则表达式 <[^>]*
是不可能匹配的。
修改后的代码如下:
const string notInsideBracketsRegex = @"(?<!<[^>]*)";
const string highlightPattern = @"<span class=""Highlight"">$0</span>";
DataBoundLiteralControl litCustomerComments = (DataBoundLiteralControl)e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Controls[0];
// Turn "term1 term2" into "(term1|term2)"
string spaceDelimited = txtTextFilter.Text.Trim();
string pipeDelimited = string.Join("|", spaceDelimited.Split(new[] " ", StringSplitOptions.RemoveEmptyEntries));
string searchPattern = "(" + pipeDelimited + ")";
searchPattern = notInsideBracketsRegex + searchPattern;
// Highlight search terms in Customer - Comments column
e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Text = Regex.Replace(litCustomerComments.Text, searchPattern, highlightPattern, RegexOptions.IgnoreCase);
【讨论】:
非常感谢!你救了我的一天! :) 这是一段很棒的代码。你应该得到比你得到的更多的选票。非常感谢。 4 年后,您的回答又帮助了另一个人。谢谢!【参考方案2】:您可以将正则表达式用于平衡组和反向引用,但我强烈建议您在此处使用parser。
【讨论】:
【参考方案3】:嗯,我不是 C# 程序员,所以我不知道它使用的正则表达式的味道,但 (?!<.>) 应该忽略标签内的任何内容。它会强制你在 HTML 代码中使用 < >,但无论如何你都应该这样做。
【讨论】:
为了匹配我在示例中描述的“类”,“类”这个词在你的正则表达式中应该放在哪里?我不明白如何使用你的正则表达式。就其本身而言,它似乎匹配整个短语中的每个字符位置。 正则表达式 "(?!<.>)" 只是一个否定的前瞻;它说,“从这个位置来看,我们不会看到看起来像标签的东西。”它不会匹配任何东西,也不会阻止匹配标签内部或外部的任何东西。【参考方案4】:编写一个可以处理 CDATA 部分的正则表达式会很困难。您可能不再假设 > 关闭标签。
例如,"<span class="CustomerName>Fred.</span> is a good customer (<![CDATA[ >10000$ ]]> )"
解决方案是(如前所述)解析器。他们在处理您在CDATA
中发现的那种混乱方面要好得多。 madgnome 的向后检查不能用于从]]>
中查找起始<![CDATA
,因为CDATA
部分可能包含文字<![CDATA
。
【讨论】:
我知道解决方案并不完美,但权衡了所有的起起落落,这是我迄今为止找到的最好的解决方案。以上是关于什么正则表达式将匹配文本,不包括 HTML 标记中的内容?的主要内容,如果未能解决你的问题,请参考以下文章