现在网站经常要给文章里的关键字自动加链接。。所在这里就涉及到给指定关键字加链接,替换字符串问题
如我的文章为:
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语言”
请问这个功能怎么实现求教了。。
最好写成一下函数。。头痛。为这个弄一半个月了
如我的文章为:
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语言”
请问这个功能怎么实现求教了。。
最好写成一下函数。。头痛。为这个弄一半个月了
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);
非常感谢,不过有点小问题。结果是这样子的:我想学习<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>有部分出入,能不能帮忙再看一下。。谢谢了。。
IList<string> list11 = new List<string>();
list11.Add("c语言视频教程");
list11.Add("C语言教程");
list11.Add("c语言");
这个要注意顺序
把数组顺序改为:string [] list11 = {"c语言视频教程","c语言教程","c语言"};后是上面的结果。。还有一点小出入,,每个关键字,只替换一次,不替换多次!,,要改哪里啊。。呵呵。。
{
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;
}
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);
-1 表示 不包含
一个复杂的替换字符串问题(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语言
*/
/// <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语言
*/
谢谢朋友,但是还有一点小问题:
就是这个,规则还有一点点问题,.虽然匹配,但该被匹配的字符串,被 <a>标签包含着,或是a标签中的title属性的值,则跳过
这个还是有点问题。。
但原来的文章中查个关键字本身已有链接,但还是会替换
非常精彩的正则匹配和匿名方法.第一眼看看到委托感到非常困惑,后来才觉悟了~
可惜楼主你的.NET1.1不支持匿名方法和泛型啊. 泛型的话你可以用非泛型版本,只是效率大打折扣,匿名方法的话我也不知道怎么改了~