请问php中url替换的问题 正则也可以?

对以下HTML进行匹配htmlstart请从以下推荐分类中选择合适的分类:<br>电脑/网络-><ahref="link1"alt="程序设计">程序设计</a><br>... 对以下HTML进行匹配

html start
请从以下推荐分类中选择合适的分类:<br>电脑/网络 -> <a href="link1" alt="程序设计">程序设计</a><br>
电脑/网络 -> 操作系统/系统故障<br>
<br>
如果没有合适的推荐分类,建议您更改分类,有助于获得准确解答 <br>
<img src=asdasda.jpg alt="test" title="你好"><br>
您还可以输入1381字<br>
test<br>
输入内容已经达到长度限制<br>
html end

匹配的词为
array(
1 => "test",
2 => "你好",
3 => "程序" ,
4 => "分类"
);

要求除了 img及a标签 外所有的都进行匹配 其中url地址为 数组的key
例如 匹配的 test 变成 <a href="1.html" title="test">test</a>
每个词只匹配一次

结果如下:

html start
请从以下推荐<a href="4.html" title="分类">分类</a>中选择合适的分类:<br>电脑/网络 -> <a href="link1" alt="程序设计">程序设计</a><br>
电脑/网络 -> 操作系统/系统故障<br>
<br>
如果没有合适的推荐分类,建议您更改分类,有助于获得准确解答 <br>
<img src=asdasda.jpg alt="test" title="你好"><br>
您还可以输入1381字<br>
<a href="1.html" title="test">test</a><br>
输入内容已经达到长度限制<br>
html end
展开
 我来答
百度网友8c3cfa1f7
2009-08-17 · 超过17用户采纳过TA的回答
知道答主
回答量:25
采纳率:0%
帮助的人:0
展开全部

首先赞扬一下楼主的提问方式:

1. 对问题描述得很清晰;

2. 给出了匹配的范例文本;

3. 指定了正则式所在的语言。

这才应该是规范合理的提问。

言归正传,先根据问题,写出正则,然后落实到PHP语言。如果对分析过程不感兴趣,请直接pagedown看答案。

1. 基础

需要匹配的关键词为:test,你好,程序,分类。

正则表达式:/test|你好|程序|分类/i

(i是表示大小写不敏感模式。如果指定匹配小写的test,则可以去掉i)

2. 限制条件

a. 不在标签内部,例如<img src=asdasda.jpg alt="test" title="你好">,里面虽然有test和你好,但这不满足要求;

b. 本身无链接。例如,<a href="link1" alt="程序设计">程序设计</a>中,>程序设计<中的程序由于处于<a..>程序设计</a>之间,同样不满足要求。

根据以上限制,写出纯粹的正则式(并不能直接用在php中):

(?<!<(?:a|img)[^<>]*)(test|你好|程序|分类)(?![^<>]*</a>)

它表示,(test|你好|程序|分类)的紧临左侧不能出现<a..标签,或者<img标签;紧临右侧不能出现</a>标签。

“紧临”二字至关重要,它将无直接关系的<>都忽略掉,才确保条件的正确执行。怎样实现这一点呢?我使用的是[^<>]*。

正则式的部分这里就交待清楚了。下面将正则式应用到PHP中。

3. php正则式

php使用的正则表达式是PCRE的,它不支持在lookbehind里使用无限量词,即(?<!<(?:a|img)[^<>]*)部分不被PCRE支持。没关系,可以修改之。

(?<!(?:<a|<img))([^<>]*)(test|你好|程序|分类)(?![^<>]*(?:>|</a>))

与2中的正则式相比,前者$1即为所求,其余部分只匹配,不消耗字符;而后者$2为所求,还需要对$1进行处理。

4. php细节

我使用preg_replace_callback函数,以便自定义替换过程。代码如下,随手注释:

<?php

//此处使用heredoc语法,以便支持复杂的长文本。

$x=<<<EOT

请从以下推荐分类中选择合适的分类:<br>电脑/网络 -> <a href="link1" alt="程序设计">程序设计</a><br>

  电脑/网络 -> 操作系统/系统故障<br>

<br>

如果没有合适的推荐分类,建议您更改分类,有助于获得准确解答 <br>

<img src=asdasda.jpg alt="test" title="你好"><br>

您还可以输入1381字<br>

test<br>

输入内容已经达到长度限制<br>

EOT;

//关键词数组

$a=array( 

1 => "test", 

2 => "你好", 

3 => "程序" ,

4 => "分类"

);

//记号数组,用于记录哪些匹配是已经替换了的。因为楼主指定“每个词只匹配一次”。

$index=array();

function compute_replacement($groups) {

 global $a;

 global $index;

 if ($index[$groups[2]])

 {

 //如果该关键词已经被处理过,那么直接返回整个字串($groups[0]),不作处理。

  return $groups[0];

 }

 

 //查询该关键词在数组中的位置,确定序号,以便生成href="1.html"之类链接地址。

 $in=array_search($groups[2],$a);

 

 //将处理过的关键词标记为已处理,避免重复。

 $index[$groups[2]]=1;

 

 //返回处理好的文本。

 return "$groups[1]<a href=\"$in.html\" title=\"$groups[2]\">$groups[2]</a>"; 

}

$r= preg_replace_callback('%(?<!<)([^<>]*)(test|你好|程序|分类)(?![^<>]*(?:>|</a>))%s', compute_replacement, $x);

echo $r;

?>

输出的结果为:

请从以下推荐分类中选择合适的<a href="4.html" title="分类">分类</a>:<br>电脑/网络 -> <a href="link1" alt="程序设计">程序设计</a><br>

  电脑/网络 -> 操作系统/系统故障<br>

<br>

如果没有合适的推荐分类,建议您更改分类,有助于获得准确解答 <br>

<img src="asdasda.jpg" alt="test" title="你好"><br>

您还可以输入1381字<br>

<a href="1.html" title="test">test</a><br>

输入内容已经达到长度限制<br></body>

注:这里的格式不好,建议去“参考资料”所指向的地址察看更易读版本的解答。

正则表达式论坛:http://regex.me

正则表达式博客:http://iregex.org

附:匹配图。高亮部分为匹配结果。

参考资料: http://regex.me/thread-113-post-317.html#pid317

推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式