我之前也有类似的问题,但最终却无法真正获得正确的答案。
我有一个函数,可以将我在输入字段中写的内容与从数据库中获取的内容进行匹配。它还带有一个始终为“ em”的参数。
函数如下:
public static string Hightlight(this string input, string phrase, string tag)
{
foreach (var item in phrase.Split(' '))
{
if (string.IsNullOrWhiteSpace(item))
continue;
input = Regex.Replace(input,
string.Format("(?<phrase>{0})", HttpUtility.HtmlEncode(item)),
string.Format("<{0}>${{phrase}}</{0}>", tag), RegexOptions.IgnoreCase);
}
return input
}
这一直有效,直到人们尝试编写Martina E
。
然后,正则表达式会尝试使用<em>
标签将我正在构建的输入中的E与所有e相匹配。
有更好的方法吗?
我希望输入的最终结果是这样的:<em>Martina</em><em>E</em>
答案 0 :(得分:1)
我建议为正则表达式替换创建一个正则表达式,该正则表达式将与标签之外的整个单词匹配名称:
return Regex.Replace(
input,
string.Format(@"(<{0}>.*?</{0}>)|(?<!\w)(?:{1})(?!\w)", tag,
string.Join("|",
phrase.Trim().Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries)
.Select(x => Regex.Escape(HttpUtility.HtmlEncode(x)))
)
),
m => m.Groups[1].Success ? m.Groups[1].Value : string.Format("<{0}>{1}</{0}>", tag, m.Value),
RegexOptions.IgnoreCase
);
请参见C# demo
简而言之:
(<{0}>.*?</{0}>)|(?<!\w)(?:{1})(?!\w)
将产生与(<em>.*?</em>)|(?<!\w)(?:Emma|E)(?!\w)
或Emma
匹配的正则表达式,如E
,该正则表达式不包含单词字符或<em>
与之间的子字符串</em>
在组1中捕获后者phrase.Trim().Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries).Select(x => Regex.Escape(HttpUtility.HtmlEncode(x))))
用空格分隔phrase
,以删除空白项目,在对HTML进行编码后,使用Regex.Escape
将每个项目转义以用于正则表达式模式,然后string.Join("|", ...)
将项目与管道字符连接起来。m => m.Groups[1].Success ? m.Groups[1].Value : string.Format("<{0}>{1}</{0}>", tag, m.Value)
用组1内容(现有的标记文本)替换,否则,添加标记的匹配。