现在网站经常要给文章里的关键字自动加链接。。所在这里就涉及到给指定关键字加链接,替换字符串问题 
如我的文章为: 
str1 = "我想学习c语言教程,我想看的是C语言视频教程,其它什么C语言教程,我都不想看。我喜欢C语言" 
我要替换的关键字数组为: str2 ={c语言视频教程,C语言教程,c语言}; 
替换加链接的关键字规则如下: 1.只替换第一次匹配的关键字,给其增加链接,即使其被 <a>标签包含着,且A标签中有title属性,title属性的值就是被匹配关键字 注意:
1.虽然匹配,但该被匹配的字符串,被 <a>标签包含着,或是a标签中的title属性的值,则跳过, 
希望最后替换后的结果为: str1 = “我想习学 <a href="http://www.21shipin.com" target="_blank" title="C语言教程">c语言教程</a>,我想看的是 <a href="http://www.21shipin.com" target="_blank" title="C语言视频教程">C语言视频教程 </a>,其它什么 <a href="http://www.21shipin.com" target="_blank" title="C语言">C语言 </a>教程,我都不想看。我喜欢C语言” 
请问这个功能怎么实现求教了。。 
最好写成一下函数。。头痛。为这个弄一半个月了

解决方案 »

  1.   

    http://topic.csdn.net/u/20090604/17/b3da6a6e-f2ab-43ca-95ef-9ac592e6226c.html?seed=991995462
      

  2.   


            public string FilterStr(string value, IList<string> filterList, bool isIgnoreCase)
            {
                string returnValue = value;
                string constFilter = "~!@#$#@!~";
                for (int i = 0; i < filterList.Count; i++)
                {
                    if (isIgnoreCase)
                    {
                        //不区分大小写
                        returnValue = System.Text.RegularExpressions.Regex.Replace(returnValue, filterList[i], constFilter + i.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    }
                    else
                    {
                        //区分大小写
                        returnValue = returnValue.Replace(filterList[i], constFilter + i.ToString());                
                    }                
                }
                for (int i = 0; i < filterList.Count; i++)
                {
                    returnValue = returnValue.Replace(constFilter + i.ToString(), string.Format("<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"{0}\">{0} </a>", filterList[i]));
                }            return returnValue;
            }string oldStr = @"我想学习c语言教程,我想看的是C语言视频教程,其它什 么C语言教程,我都不想看。我喜欢C语言";            IList<string> list11 = new List<string>();
                list11.Add("c语言视频教程");
                list11.Add("C语言教程");
                list11.Add("c语言");            bool isIgnoreCase = true;            string newStr = new Program().FilterStr(oldStr, list11, isIgnoreCase);
      

  3.   


    非常感谢,不过有点小问题。结果是这样子的:我想学习<a href="http://www.21shipin.com" target="_blank" title="c语言">c语言 </a>教程,我想看的是<a href="http://www.21shipin.com" target="_blank" title="c语言视频教程">c语言视频教程 </a>,其它什么<a href="http://www.21shipin.com" target="_blank" title="c语言">c语言 </a>教程,我都不想看。我喜欢<a href="http://www.21shipin.com" target="_blank" title="c语言">c语言 </a>有部分出入,能不能帮忙再看一下。。谢谢了。。
      

  4.   


    IList<string> list11 = new List<string>();
                list11.Add("c语言视频教程");
                list11.Add("C语言教程");
                list11.Add("c语言");
    这个要注意顺序
      

  5.   

    我想学习<a href="http://www.21shipin.com" target="_blank" title="c语言教程">c语言教程 </a>,我想看的是<a href="http://www.21shipin.com" target="_blank" title="c语言视频教程">c语言视频教程 </a>,其它什么<a href="http://www.21shipin.com" target="_blank" title="c语言教程">c语言教程 </a>,我都不想看。我喜欢<a href="http://www.21shipin.com" target="_blank" title="c语言">c语言 </a>
    把数组顺序改为:string [] list11 = {"c语言视频教程","c语言教程","c语言"};后是上面的结果。。还有一点小出入,,每个关键字,只替换一次,不替换多次!,,要改哪里啊。。呵呵。。
      

  6.   

            public string FilterStr(string value, IList<string> filterList, bool isIgnoreCase, bool isReplaceAll)
            {
                string returnValue = value;
                string constFilter = "~!@##@!~";
                for (int i = 0; i < filterList.Count; i++)
                {
                    if (isIgnoreCase)
                    {
                        //不区分大小写
                        returnValue = System.Text.RegularExpressions.Regex.Replace(returnValue, filterList[i], constFilter + i.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    }
                    else
                    {
                        //区分大小写
                        returnValue = returnValue.Replace(filterList[i], constFilter + i.ToString());
                    }
                }
                string[] array;
                for (int i = 0; i < filterList.Count; i++)
                {
                    if (isReplaceAll)
                    {
                        returnValue = returnValue.Replace(constFilter + i.ToString(), string.Format("<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"{0}\">{0} </a>", filterList[i]));
                    }
                    else
                    {
                        if (returnValue.Contains(constFilter + i.ToString()))
                        {
                            array = System.Text.RegularExpressions.Regex.Split(returnValue, constFilter + i.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                            for (int j = 0; j < array.Length; j++)
                            {
                                if (j == 0)
                                {
                                    returnValue = string.Format("{0}<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"{1}\">{1} </a>", array[0], filterList[i]);
                                }
                                else
                                {
                                    returnValue += string.Format("{0}{1}", array[j], (j == array.Length - 1 ? "" : filterList[i]));
                                }
                            }
                        }
                    }
                }            return returnValue;
            }
      

  7.   


    string oldStr = @"我想学习c语言教程,我想看的是C语言视频教程,其它什 么C语言教程,我都不想看。我喜欢C语言我想学习c语言教程,我想看的是C语言视频教程,其它什 么C语言教程,我都不想看。我喜欢C语言";            IList<string> list11 = new List<string>();
                list11.Add("c语言视频教程");
                list11.Add("C语言教程");
                list11.Add("c语言");
                bool isIgnoreCase = true;
                string newStr = new Program().FilterStr(oldStr, list11, isIgnoreCase, false);
      

  8.   

    string 不包含对Contains定义我的是vs2003??咋搞???请教啊。。
      

  9.   

    用 indexOf 判断是否等于 -1 
    -1 表示 不包含
      

  10.   

    楼主两个月以前的帖子中我已经给实现了
    一个复杂的替换字符串问题(SEO常要用到)
    但是楼主说复杂,不知道楼主的复杂指的是代码逻辑复杂,还是正则复杂其实楼主的需求本身就很复杂,如果以正则来实现,这种复杂度是免不了的当然也可以自己写有穷自动机来实现,因为没有正则这么抽象,逻辑会清晰得多,但是代码会很长,开发效率也自然降下来了对上一帖中的实现方法做了些优化
    string str1 = "我想学习c语言教程,我想看的是C语言视频教程,其它什么C语言教程,我都不想看。我喜欢C语言";
    Regex reg = new Regex(@"(?i)(?:^|(?<!<a\b(?>[^<>]*))>)(?>[^<>]*)(?:<|$)");
    //如果关键字有包含关系时,要求被包含的关键字在前
    List<string> tags = new List<string>(new string[] { "c语言", "C语言教程", "c语言视频教程" });
    int length = 0;
    string temp = string.Empty;
    string result = reg.Replace(str1, delegate(Match m)
    {
        temp = m.Value;
        length = temp.Length;
        for (int i = tags.Count - 1; i >= 0; i--)
        {
            temp = Regex.Replace(temp, @"(?is)^((?:(?:(?!" + Regex.Escape(tags[i]) + @"|</?a\b).)*<a\b(?:(?!</?a\b).)*</a>)*(?:(?!" + Regex.Escape(tags[i]) + @"|</?a\b).)*)(?<tag>" + Regex.Escape(tags[i]) + @")", @"$1<a href=""http://www.21shipin.com"" target=""_blank"" title=""${tag}"">${tag}</a>");
            if (length != temp.Length)
            {
                tags.Remove(tags[i]);
            }
            length = temp.Length;
        }
        return temp;
    });
    richTextBox2.Text = result;
    /*------------输出------------
    我想学习<a href="http://www.21shipin.com" target="_blank" title="c语言教程">c语言教程</a>,我想看的是<a href="http://www.21shipin.com" target="_blank" title="C语言视频教程">C语言视频教程</a>,其它什么<a href="http://www.21shipin.com" target="_blank" title="C语言">C语言</a>教程,我都不想看。我喜欢C语言
    */
      

  11.   

    写成方法也一样
    /// <summary>
    /// 给关键字加链接,同一关键字只加一次
    /// </summary>
    /// <param name="src">源字符串</param>
    /// <param name="keys">关键字泛型</param>
    /// <returns>替换后结果</returns>
    private string keyAddUrl(string src, List<string> keys)
    {
        Regex reg = new Regex(@"(?i)(?:^|(?<!<a\b(?>[^<>]*))>)(?>[^<>]*)(?:<|$)");
        int length = 0;
        string temp = string.Empty;
        return reg.Replace(src, delegate(Match m)
        {
            temp = m.Value;
            length = temp.Length;
            for (int i = keys.Count - 1; i >= 0; i--)
            {
                temp = Regex.Replace(temp, @"(?is)^((?:(?:(?!" + Regex.Escape(keys[i]) + @"|</?a\b).)*<a\b(?:(?!</?a\b).)*</a>)*(?:(?!" + Regex.Escape(keys[i]) + @"|</?a\b).)*)(?<tag>" + Regex.Escape(keys[i]) + @")", @"$1<a href=""http://www.21shipin.com"" target=""_blank"" title=""${tag}"">${tag}</a>");
                if (length != temp.Length)
                {
                    keys.Remove(keys[i]);
                }
                length = temp.Length;
            }
            return temp;
        });
    }
    //调用
    string str1 = "我想学习c语言教程,我想看的是C语言视频教程,其它什么C语言教程,我都不想看。我喜欢C语言";
    List<string> keys = new List<string>(new string[] { "c语言", "C语言教程", "c语言视频教程" });
    string result = keyAddUrl(str1, keys);
    richTextBox2.Text = result;
    /*------------输出------------
    我想学习<a href="http://www.21shipin.com" target="_blank" title="c语言教程">c语言教程</a>,我想看的是<a href="http://www.21shipin.com" target="_blank" title="C语言视频教程">C语言视频教程</a>,其它什么<a href="http://www.21shipin.com" target="_blank" title="C语言">C语言</a>教程,我都不想看。我喜欢C语言
    */
      

  12.   

    我的是.net 1.1 很多东东都不能用啊。。唉郁闷。。
      

  13.   


    谢谢朋友,但是还有一点小问题:
    就是这个,规则还有一点点问题,.虽然匹配,但该被匹配的字符串,被 <a>标签包含着,或是a标签中的title属性的值,则跳过
    这个还是有点问题。。
    但原来的文章中查个关键字本身已有链接,但还是会替换
      

  14.   


    非常精彩的正则匹配和匿名方法.第一眼看看到委托感到非常困惑,后来才觉悟了~
    可惜楼主你的.NET1.1不支持匿名方法和泛型啊. 泛型的话你可以用非泛型版本,只是效率大打折扣,匿名方法的话我也不知道怎么改了~
      

  15.   

    楼主 Sandy945,和过客应该给分的吧
      

  16.   

    Sandy945,和过客有空帮我看看啊。。