C# 突出显示字符串中的多个关键字,忽略C中添加的HTML#

C# 突出显示字符串中的多个关键字,忽略C中添加的HTML#,c#,html,regex,C#,Html,Regex,我有一个扩展,它通过一个字符串循环查找任意数量的关键字(或搜索词)的所有实例。当找到匹配项时,它会在每个关键字周围添加一个span标记,以高亮显示显示的关键字 public static string HighlightKeywords( this string input, string keywords ) { if( input == String.Empty || keywords == String.Empty ) {

我有一个扩展,它通过一个字符串循环查找任意数量的关键字(或搜索词)的所有实例。当找到匹配项时,它会在每个关键字周围添加一个span标记,以高亮显示显示的关键字

        public static string HighlightKeywords( this string input, string keywords )
    {
        if( input == String.Empty || keywords == String.Empty )
        {
            return input;
        }

        string[] words = keywords.Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries );

        foreach( string word in words )
        {
            input = Regex.Replace( input, word, string.Format( "<span class=\"highlight\">{0}</span>", "$0" ), RegexOptions.IgnoreCase );
        }
        return input;
    }
公共静态字符串HighlightKeywords(此字符串输入,字符串关键字)
{
if(输入==String.Empty | |关键字==String.Empty)
{
返回输入;
}
string[]words=keywords.Split(新[]{''},StringSplitOptions.RemoveEmptyEntries);
foreach(单词中的字符串)
{
input=Regex.Replace(input,word,string.Format(“{0}”,“$0”),RegexOptions.IgnoreCase);
}
返回输入;
}
除了使用与添加的span标记匹配的搜索词外,该方法工作良好

不可靠输出的示例:

字符串“类是高的”

关键词:“班级高”

结果是不可靠的HTML输出:input=“classspan>很高”

因此,它需要在原始字符串中查找第一个关键字,添加装饰性HTML,然后在修改后的字符串中查找下一个关键字,添加更多HTML并造成混乱

在搜索每个关键字时,有没有办法避免修饰的关键字

更新:

考虑到不区分大小写很重要,我探索了各种不区分大小写的替换方法,并取得了部分成功。搜索函数忽略大小写,但返回关键字中使用的大小写,并将其替换为原始文本,例如搜索“HIGH”返回“class is HIGH”。这看起来很糟糕

于是,我又开始使用正则表达式(叹气)。我成功地重写了我的扩展,如下所示,它似乎工作得很好,但我想知道这个扩展到底有多高效。我欢迎任何关于改进此代码或在没有Regex的情况下实现此功能的评论

    public static string HighlightKeywords( this string input, string keywords, string classname )
    {
        if( input == String.Empty || keywords == String.Empty )
        {
            return input;
        }

        string[] words = keywords.Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries );

        foreach( string word in words )
        {
            input = Regex.Replace( input, Regex.Escape( word ), string.Format( "<!--{0}-->", Regex.Unescape( "$0" ) ), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled );
        }

        var s = new StringBuilder( );
        s.Append( input );
        s.Replace( "<!--", "<span class='" + classname + "'>" ).Replace( "-->", "</span>" );

        return s.ToString( );
    }
公共静态字符串HighlightKeywords(此字符串输入、字符串关键字、字符串类名)
{
if(输入==String.Empty | |关键字==String.Empty)
{
返回输入;
}
string[]words=keywords.Split(新[]{''},StringSplitOptions.RemoveEmptyEntries);
foreach(单词中的字符串)
{
input=Regex.Replace(input,Regex.Escape(word),string.Format(“,Regex.Unescape($0”)),RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
}
var s=新的StringBuilder();
s、 追加(输入);
s、 替换(“,”);
返回s.ToString();
}
方法略有不同。 添加StringBuilder会更好

  public static string HighlightKeywords(this string input, string keywords)
{
  if (input == String.Empty || keywords == String.Empty)
  {
    return input;
  }

  string[] words = keywords.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.ToLower()).ToArray();
  string[] originalWords = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  input = string.Empty;

  foreach (var word in originalWords.Select((value, i) => new { i, value }))
  {
    input += words.Contains(word.value.ToLower()) ? string.Format("<span class=\"highlight\">{0}</span>", word.value) : word.value;
    if (originalWords.Length - 1 != word.i) input += " ";
  }
  return input;
}
公共静态字符串HighlightKeywords(此字符串输入,字符串关键字)
{
if(输入==String.Empty | |关键字==String.Empty)
{
返回输入;
}
string[]words=keywords.Split(新[]{''},StringSplitOptions.RemoveEmptyEntries)。选择(x=>x.ToLower()).ToArray();
string[]originalWords=input.Split(新的[]{''},StringSplitOptions.RemoveEmptyEntries);
输入=string.Empty;
foreach(originalWords.Select中的var单词((value,i)=>new{i,value}))
{
input+=words.Contains(word.value.ToLower())?string.Format(“{0}”,word.value):word.value;
如果(originalWords.Length-1!=word.i)输入+=”;
}
返回输入;
}

试试这个简单的改变:

public static string HighlightKeywords(this string input, string keywords)
{
    if (input == String.Empty || keywords == String.Empty)
    {
        return input;
    }

    return Regex.Replace(
        input,
        String.Join("|", keywords.Split(' ').Select(x => Regex.Escape(x))),
        string.Format("<span class=\"highlight\">{0}</span>", "$0"),
        RegexOptions.IgnoreCase);
}
公共静态字符串HighlightKeywords(此字符串输入,字符串关键字)
{
if(输入==String.Empty | |关键字==String.Empty)
{
返回输入;
}
返回正则表达式。替换(
输入,
String.Join(“|”,关键字.Split(“”).Select(x=>Regex.Escape(x)),
string.Format(“{0}”,“$0”),
RegexOptions.IgnoreCase);
}
Regex
为您完成这项工作


通过输入
“类高”。HighlightKeywords(“类高”)
您得到了
“类高”

您考虑过HTML敏捷包吗?即使没有完美的答案,我也看到了一些不错的努力。请看我的答案。它不需要像那样使用晦涩的编码就可以完成这项工作。我喜欢使用StringBuilder的这种方法,但它不允许不区分大小写的搜索。这很好,但只搜索整个单词,而我的扩展将查找部分匹配。@Scho-你说的部分匹配是什么意思?在匹配词方面似乎没有任何差异。好的,尝试搜索搜索词“clas igh”。@Scho-我的代码给出
“类高”
。这不是你想要的吗?我不得不说@Enigmativity,你的代码非常聪明和干净。非常感谢你。