当前位置: 首页 > 图文教程 > 网络编程 > PHP > PHP教程:preg_replace_callback()函数

PHP
利用discuz实现PHP大文件上传应用实例代码
php 遍历显示文件夹下所有目录、所有文件的函数,没有分页的代码
php在字符串中查找另一个字符串
php下HTTP Response中的Chunked编码实现方法
PHP实现定时生成HTML网站首页实例代码
PHP下一个非常全面获取图象信息的函数
PHP strtr() 函数使用说明
php 删除无限级目录与文件代码共享
php AJAX实例根据邮编自动完成地址信息
php miniBB中文乱码问题解决方法
cmd下运行php脚本
PHP 遍历XP文件夹下所有文件
php 移除数组重复元素的一点说明
discuz论坛 用户登录 后台程序代码
Optimizer与Debugger兼容性问题的解决方法
Zend Studio 无法启动的问题解决方法
php 页面执行时间计算代码
php smarty的预保留变量总结
php获取网页内容方法总结
php读取msn上的用户信息类

PHP教程:preg_replace_callback()函数


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 308 ::
收藏到网摘: n/a

最近碰到一个问题,要在一段HTML代码的链接中加一个参数,比如其中由一个A标签是这样的:

1
<a href="http://www.example.com/aaa.php">链接文字</a>

我就要在 aaa.php 的后面加上一个参数使其变成 aaa.php?request=xxx ,但问题是不是所有的链接都是aaa.php这样的形式,可能后面已经有了别的参数,比如 aaa.php?id=111 ,这样加的时候就需要把链接变成 aaa.php?id=111&request=xxx 。

由于要处理的是一大块HTML,所以首先想到的解决方案是正则替换,不过 preg_replace 不能做条件判断,只能做一种替换,然后我就找到了 preg_replace_callback() 这个函数,大喜,以为找到了银弹。这个东西的用法和 preg_replace() 函数几乎一样,不过它提供了一个 callback 函数,可以在替换的时候根据条件替换。在PHP手册中提供了这么一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php // 此文本是用于 2002 年的, // 现在想使其能用于 2003 年 $text = "April fools day is 04/01/2002\n"; $text.= "Last christmas was 12/24/2001\n";
  // 回调函数 function next_year($matches) { // 通常:$matches[0] 是完整的匹配项 // $matches[1] 是第一个括号中的子模式的匹配项 // 以此类推 return $matches[1].($matches[2]+1); }
  echo preg_replace_callback( "|(\d{2}/\d{2}/)(\d{4})|", "next_year", $text);
  // 结果为: // April fools day is 04/01/2003 // Last christmas was 12/24/2002
?>

看了这个例子之后我以为只要把想要替换的内容替换掉就OK了,比如我只想更改捕获的第二个匹配项,只需要把 $matches[2]中的内容改一下返回就行了。然后我就写了下面的代码测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$content = '<a href="http://www.example.com/aaa.php">链接1</a><a href="http://www.example.com/aaa.php?id=111">链接2</a>';
 
$content = preg_replace_callback('/href=[\'|"](.*?)[\'|"]/', 'add_request', $content);
 
// 下面是 add_request 函数定义
 
function add_source($matches)
{ if(strpos($matches[1], '?')) { return $matches[1].'&request=xxx'; } else { return $matches[1].'?request=xxx'; }
}

不过实验之后却发现把代码替换得乱七八糟,我找了半天都没发现哪里出错了。后来仔细检查了一下才恍然大悟,我被手册上的例子误导了!!其实这个函数会替换匹配的整个内容,即 /href=[\'|"](.*?)[\'|"]/ (包括 href),而不只是 (.*?) 所捕获的东西。而手册例子中的正则是这样的:|(\d{2}/\d{2}/)(\d{4})| ,它的所有部分都是在()内的,所以替换成 $matches[1].($matches[2]+1) 自然不会有问题,但是它却让我误以为这个函数会有针对性地替换 $matches[1] 和 $matches[2]中的内容,事实上它还是替换整个正则匹配的内容,即 $matches[0]中的内容,而加上的括号只是为了我们对字符串操作方便而已!了解这一点之后,修改了代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$content = '<a href="http://www.example.com/aaa.php">链接1</a><a href="http://www.example.com/aaa.php?id=111">链接2</a>';
 
$content = preg_replace_callback('/href=[\'|"](.*?)[\'|"]/', 'add_request', $content);
 
// 下面是 add_request 函数定义
 
function add_source($matches)
{ if(strpos($matches[1], '?')) { return 'href="'.$matches[1].'&request=xxx"'; //注意,这里和下面都加上了正则里括号外的东西:href=" } else { return 'href="'.$matches[1].'?request=xxx"'; }
}

改好之后,测试正常。

一点学习笔记,记录在此。