头次发帖就把分全散了,求解正则表达式修改

gs8716 2010-05-08 05:44:09
先说下需求:
对一篇文章查找搜索关键字,并进行替换,变成链接形式

要求:
1、标签内的内容不参与替换,比如:<p title="关键字"> 虽然含有关键字,但不进行替换
2、本身是链接的内容不参与替换,如:<a>关键字</a>
3、<pre></pre>标签内的内容不参与替换,如:<pre>关键字</pre>
4、做到一个关键字在一篇文章中只有一个被替换成链接(因为关键字很多,都替换成链接,整篇文章十分不雅)

再提供一点数据:
如我的文章为:
str1 = "我想学习c语言教程,我想看的是C语言视频教程,其它什么<a href='http://www.21shipin.com' target='_blank'>C语言</a>教程,我都不想看。我喜欢C语言"


我要替换的关键字数组为:
str2 ={c语言视频教程,C语言教程,c语言};
详见http://topic.csdn.net/u/20090604/17/b3da6a6e-f2ab-43ca-95ef-9ac592e6226c.html?seed=991995462
http://topic.csdn.net/u/20091028/13/df7cd47d-0f30-4361-9695-a6aa547b8d7a.html


目前我已整理出大部分代码,但是还不完善的地方就是加了链接的关键字还会再次加上,望高手能修改正则表达式达到完美!

string str1 = "我想学习c语言教程,我想看的是C语言视频教程,其它什么<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"C语言\">C语言</a>教程,我都不想看。我喜欢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;
});
Response.Write(result);




private string RegReplace(Match m)
{
int length = 0;
List<string> tags = new List<string>(new string[] { "c语言视频教程", "C语言教程", "c语言" }); //关键字如果可能出现包含关系,被包含的放在后面

List<string> list = new List<string>();
string temp = string.Empty;
string t = string.Empty;
temp = m.Value;
length = temp.Length;
foreach (string tag in tags)
{
t = Regex.Escape(tag);
temp = Regex.Replace(temp, @"(?is)^((?:(?:(?!" + t + @"|</?a\b).)*<a\b(?:(?!</?a\b).)*</a>)*(?:(?!" + t + @"|</?a\b).)*)(?<tag>" + Regex.Escape(tag) + @")", @"$1<a href=""http://www.21shipin.com"" target=""_blank"" title=""${tag}"">${tag}</a>");
if (length != temp.Length)
{
list.Add(tag);
}
length = temp.Length;
}
foreach (string s in list)
{
tags.Remove(s);
}
list.Clear();
return temp;
}
...全文
247 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
sail8011 2012-07-31
  • 打赏
  • 举报
回复
您好,请问如果不是只替换一次关键词,而是替换所有关键字,怎么写啊
kofkofs 2011-09-27
  • 打赏
  • 举报
回复
新手测试了一下非常好,再请问lxcnn大哥怎样替换URL为不同链接啊
-过客- 2010-05-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 gs8716 的回复:]
有两个c语言加了链接
[/Quote]

上次回帖就存在这样的疑问,楼主的需求中是否需要过滤原来已有链接的关键字,现在看来是要先做下预处理的

/// <summary>
/// 处理关键字,去除已添加链接的关键字
/// </summary>
/// <param name="src">源字符串</param>
/// <param name="keys">关键字列表</param>
/// <returns>处理后结果</returns>
private List<string> removeRepKey(string src, List<string> keys)
{
Regex reg = new Regex(@"(?is)<a\b[^>]*>(.*?)</a>");
MatchCollection mc = reg.Matches(src);
foreach (Match m in mc)
{
for (int i = keys.Count - 1; i >= 0; i--)
{
if (keys[i].ToLower() == m.Groups[1].Value.ToLower())
{
keys.RemoveAt(i);
}
}
}
return keys;
}

/// <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|pre)\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 = "我想加个<pre>c语言教程,c语言</pre>还学习c语言教程,<p title=\"c语言\">c语言</p>,我想看的是C语言视频教程,其它什么<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"C语言\">C语言</a>教程,我都不想看。我喜欢C语言,还是C语言。";
List<string> keys = new List<string>(new string[] { "c语言", "C语言教程", "c语言视频教程" });
keys = removeRepKey(str1, keys);
string result = keyAddUrl(str1, keys);
richTextBox2.Text = result;
gs8716 2010-05-11
  • 打赏
  • 举报
回复
目前还没有发现在什么不满足的地方,就这样了,结帖了。谢谢过客!!!
-过客- 2010-05-11
  • 打赏
  • 举报
回复
5楼不够严谨,改下正则

/// <summary>
/// 处理关键字,去除已添加链接的关键字
/// </summary>
/// <param name="src">源字符串</param>
/// <param name="keys">关键字列表</param>
/// <returns>处理后结果</returns>
private List<string> removeRepKey(string src, List<string> keys)
{
Regex reg = new Regex(@"(?is)<a\b[^>]*>(.*?)</a>");
MatchCollection mc = reg.Matches(src);
foreach (Match m in mc)
{
for (int i = keys.Count - 1; i >= 0; i--)
{
if (keys[i].ToLower() == m.Groups[1].Value.ToLower())
{
keys.RemoveAt(i);
}
}
}
return keys;
}
/// <summary>
/// 给关键字加链接,同一关键字只加一次
/// </summary>
/// <param name="src">源字符串</param>
/// <param name="keys">关键字列表</param>
/// <returns>替换后结果</returns>
private string keyAddUrl(string src, List<string> keys)
{
Regex reg = new Regex(@"(?in)[^<>]+(?=(<(?!/(pre|a))[^<>]*>[^<>]*)*(<(a|pre)\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 = "我想加个<pre><b>c语言教程</b>,c语言</pre>还学习c语言教程,<p title=\"c语言\">c语言</p>,我想看的是C语言视频教程,其它什么<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"C语言\">C语言</a>教程,我都不想看。我喜欢C语言,还是C语言。";
List<string> keys = new List<string>(new string[] { "c语言", "C语言教程", "c语言视频教程" });
keys = removeRepKey(str1, keys);
string result = keyAddUrl(str1, keys);
richTextBox2.Text = result;
KissXYL 2010-05-10
  • 打赏
  • 举报
回复
这是客客最近弄过的最复杂的郑则问题。
gs8716 2010-05-10
  • 打赏
  • 举报
回复
string str1 = "我想学习c语言教程,<p title=\"c语言\">c语言</p>,我想看的是C语言视频教程,其它什么<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"C语言\">C语言</a>教程,我都不想看。我喜欢C语言,还是C语言。"; 只是加了一点<p title=\"c语言\">c语言</p>,结果是
我想学习<a href="http://www.21shipin.com" target="_blank" title="c语言教程">c语言教程</a>,<p title="c语言"><a href="http://www.21shipin.com" target="_blank" title="c语言">c语言</a></p>,我想看的是<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语言,还是C语言。


有两个c语言加了链接


还有第三条不满足 加个<pre>c语言,c语言</pre>还是有两个c语言加了链接,另外<pre>中的内容不用加

请高手修正一下!!
gs8716 2010-05-10
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 kissxyl 的回复:]

这是过客最近弄过的最复杂的郑则问题。
[/Quote]

我看见正则表达式就头晕
-过客- 2010-05-09
  • 打赏
  • 举报
回复
都是那个固化分组惹的祸

/// <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语言视频教程,其它什么<a href=\"http://www.21shipin.com\" target=\"_blank\" title=\"C语言\">C语言</a>教程,我都不想看。我喜欢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>教程,我都不想看。我喜欢<a href="http://www.21shipin.com" target="_blank" title="C语言">C语言</a>,还是C语言。
*/


没做太多测试,如果还有不满足的给出实例

62,052

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧