Home  >  Q&A  >  body text

php - 关于str_replace_once怎么只替换内容不替换<img>里面alt标签

关于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>//不操作
.....
这些的时候虽然有包含数组的内容但是不对它们进行替换。

PHP中文网PHP中文网2724 days ago539

reply all(1)I'll reply

  • 黄舟

    黄舟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);
    }

    reply
    0
  • Cancelreply