关于str_replace_once($needle,$replace,$haystack) 怎么只替换内容不替换<img>里面alt、title标签
原代码如下
代码1:
public function str_replace_once($needle,$replace,$haystack)
{
$pos = strpos($haystack, $needle);
if ($pos === false)
{
return $haystack;
}
return substr_replace($haystack, $replace, $pos, strlen($needle));
}
求助怎么可以替换字符的时候只替换文字内容,不替换图片<img >里面的alt 跟title字符
我的目的就是,有一篇文章$str,然后有一数组$arr=array("小草","小花","小狗","杨柳");我要把文章里面包含有数组内容的都替换成小草小花之类的,相当于文章内链吧,但是当遇到
<img alt="小草">//不操作
aaa//不操作
<p title="杨柳">aa</p>//不操作
.....
这些的时候虽然有包含数组的内容但是不对它们进行替换。
黄舟2017-04-11 10:18:27
字符串替换已经满足不了你了,请尝试正则表达式。
或者处理标签的话,可以试试xml解析的那些插件。
昨天是手机回答的,所以没有详细说明。
这里你要匹配标签之外字符,其实观察一下就能发现,只要匹配>
之后<
之前的字符就行了。所以用断言(?<=>)
匹配>
而不包括>
,用断言(?=<)
匹配<
而不包括<
。用.*
来匹配任意字符,就得到模式/(?<=>).*(?=<)/
(使用/
作为分隔符,表示模式的起止)。
但是HTML中的文字还可能有换行,而.*
匹配默认不包括换行,因此用s
修饰符来让它匹配换行。但是这样就扩大了匹配范围,因此要用.*?
来做最小匹配,这样就得到了最终的模式:/(?<=>).*?(?=<)/s
(可以把*
改成+
来不匹配无字符的情况,也可以更进一步优化不匹配空白字符等,这个你自己研究吧)。
这里不能用preg_replace
直接替换,因为你要替换的不是上面匹配的结果,而是在结果之中再替换需要的内容,因此用preg_replace_callback
来处理,这个函数调用另一个函数来处理每个匹配。
所以代码应该是这样:
//这是修改之后的函数,我没有改变名称
function str_replace_once($needle,$replace,$haystack) {
//这里使用了匿名函数作为回调函数,注意在PHP 5.3.0以上才能使用
$callback = function ($matches) use ($needle,$replace) {
//这里做你需要的替换处理,我只是简单替换,如果要更复杂的处理请自行解决。
//$matches是preg_replace_callback传入的数组,索引[0]是完整匹配,[1]是第一个子匹配,以此类推
return str_replace($needle, $replace, $matches[0]);
};
return preg_replace_callback('/(?<=>).*?(?=<)/s', $callback, $haystack);
}