php preg_replace让人很无语的问题

张映 发表于 2010-07-02

分类目录: php

标签:,

先说一下,我是怎么遇到这个问题的,写html的时候没要求换行<br>,线条<hr>加/。后来呢客户要示把<br>,<hr>换成<br />,<hr />,因为网站有统一的入口,所以我把html输出的地方加了,正则进行替换,这是最方便的一种方式,所以在做这个工作之前我在本地做了一下测试,preg_replace我经常用,算是很熟了,但是用的过程中还是遇到一些问题,挺郁闷,我把问题提出来:

一,这种情况是我想要的情况

<?php

$string = "asdf <br> 444444 <br  ><br   /> 3333333 <hr> bbbbb <hr > 12312.";

$patterns[0] = "/<hr[^<>\/]*>/i";            //匹配$string里面没有/的hr
$patterns[1] = "/<br[^<>\/]*>/i";            //匹配$string里面没有/的br

$replacements[0] = "<hr />";            //将string里面的没有/的hr,换成有/的hr
$replacements[1] = "<br />";            //将string里面的没有/的br,换成有/的br

$aaa = preg_replace($patterns, $replacements, $string);    //进行替换

echo $aaa;    //结果是:asdf <br /> 444444 <br /><br   /> 3333333 <hr /> bbbbb <hr /> 12312.
?>

二,问题情况

<?php

$string = "asdf <br> 444444 <br  ><br   /> 3333333 <hr> bbbbb <hr > 12312.";

$patterns[0] = "/<hr[^<>\/]*>/i";            //匹配$string里面没有/的hr
$patterns[1] = "/<br[^<>\/]*>/i";            //匹配$string里面没有/的br

$replacements[1] = "<br />";            //将string里面的没有/的br,换成有/的br
$replacements[0] = "<hr />";            //将string里面的没有/的hr,换成有/的hr

$aaa = preg_replace($patterns, $replacements, $string);    //进行替换

echo $aaa;    //结果是:asdf <hr /> 444444 <hr /><br   /> 3333333 <br /> bbbbb <br /> 12312.
?>

不知道你有没有发现上面二个例子的不同呢?不同之处就在$replacements[0]在前一行,还是在后一行的问题,就这么一点点的区别,带来的结果却是完全相反的。请使用者小心使用。

$replacements[0] = "<hr />";
$replacements[1] = "<br />";

$replacements[1] = "<br />";
$replacements[0] = "<hr />";

不明白的地方就是上面二个例子中,都以数字为下标,谁在前在后不都是一样的吗?二个例子当中,我把数组都打印出来了,完全一样,难道php读取数组数据,还会去看看谁在前赋值,谁在后赋值?

如果 patternreplacement 都是数组,将以其键名在数组中出现的顺序来进行处理。这不一定和索引的数字顺序相同。如果使用索引来标识哪个 pattern 将被哪个 replacement 来替换,应该在调用 preg_replace() 之前用 ksort() 对数组进行排序。

上面的一段话是在官方网站上找到的,已经很明显的说明了,不一定和索引的数字顺序相同。如果不以数字顺序来定位的话,我很想知道他是怎么区分,$replacements[0] = "<hr />"; 在前在后的,难道真是以赋值的前后来区分。

如果真是以赋值的前后顺序来区分,那为什么还要用数组,并且还可以带有下标,这不是引人误入歧途吗?

有没有更有说服力的解释呢?

在向请教后,给了一个不错的解答$aaa = preg_replace("/<(br|hr)[^<>]*>/iU", "<$1 />", $string);



转载请注明
作者:海底苍鹰
地址:http://blog.51yip.com/php/892.html

2 条评论

  1. 4wei.cn 留言

    $patterns[0] = "/]*?>/i"; //匹配$string里面没有/的hr
    $patterns[1] = "/]*?>/i"; //匹配$string里面没有/的br

  2. 笑望书 留言

    呵呵,正则真强大,preg_replace真强大,我是来学习的。博主的正则规则忘记加非贪婪了, 这一点要值得注意