preg_replace 以及弃用的e
preg_replace
(PHP 4, PHP 5)
preg_replace — 执行一个正则表达式的搜索和替换
说明 ¶
$pattern
, mixed $replacement
, mixed $subject
[, int $limit
= -1 [, int &$count
]] )搜索subject
中匹配pattern
的部分, 以replacement
进行替换。
参数 ¶
pattern
-
要搜索的模式。可以使一个字符串或字符串数组。
可以使用一些PCRE修饰符, 包括被弃用的'e'(PREG_REPLACE_EVAL),可以为这个函数指定。
replacement
-
用于替换的字符串或字符串数组。如果这个参数是一个字符串,并且
pattern
是一个数组,那么所有的模式都使用这个字符串进行替换。如果pattern
和replacement
都是数组,每个pattern
使用replacement
中对应的 元素进行替换。如果replacement
中的元素比pattern
中的少, 多出来的pattern
使用空字符串进行替换。replacement
中可以包含后向引用\\n 或(php 4.0.4以上可用)$n,语法上首选后者。 每个 这样的引用将被匹配到的第n个捕获子组捕获到的文本替换。 n 可以是0-99,\\0和$0代表完整的模式匹配文本。 捕获子组的序号计数方式为:代表捕获子组的左括号从左到右, 从1开始数。如果要在replacement
中使用反斜线,必须使用4个("\\\\",译注:因为这首先是php的字符串,经过转义后,是两个,再经过 正则表达式引擎后才被认为是一个原文反斜线)。当在替换模式下工作并且后向引用后面紧跟着需要是另外一个数字(比如:在一个匹配模式后紧接着增加一个原文数字), 不能使用\\1这样的语法来描述后向引用。比如, \\11将会使preg_replace() 不能理解你希望的是一个\\1后向引用紧跟一个原文1,还是 一个\\11后向引用后面不跟任何东西。 这种情况下解决方案是使用\${1}1。 这创建了一个独立的$1后向引用, 一个独立的原文1。
当使用被弃用的 e 修饰符时, 这个函数会转义一些字符(即:'、"、 \ 和 NULL) 然后进行后向引用替换。当这些完成后请确保后向引用解析完后没有单引号或 双引号引起的语法错误(比如: 'strlen(\'$1\')+strlen("$2")')。确保符合PHP的 字符串语法,并且符合eval语法。因为在完成替换后, 引擎会将结果字符串作为php代码使用eval方式进行评估并将返回值作为最终参与替换的字符串。
subject
-
要进行搜索和替换的字符串或字符串数组。
如果
subject
是一个数组,搜索和替换回在subject
的每一个元素上进行, 并且返回值也会是一个数组。 limit
-
每个模式在每个
subject
上进行替换的最大次数。默认是 -1(无限)。 count
-
如果指定,将会被填充为完成的替换次数。
返回值 ¶
如果subject
是一个数组, preg_replace()返回一个数组, 其他情况下返回一个字符串。
如果匹配被查找到,替换后的subject
被返回,其他情况下 返回没有改变的 subject
。如果发生错误,返回 NULL
。
错误/异常 ¶
当传入 "\e" 修饰符的时候,会产生一个 E_DEPRECATED
级别的错误。
更新日志 ¶
版本 | 说明 |
---|---|
5.5.0 | /e 修饰符已经被弃用了。使用 preg_replace_callback() 代替。参见文档中 PREG_REPLACE_EVAL 关于安全风险的更多信息。 |
5.1.0 | 增加参数count . |
4.0.4 | 增加replacement 参数中的'$n'用法。 |
4.0.2 | 增加了参数limit |
范例 ¶
Example #1 使用后向引用紧跟数值原文
<?php
$string = 'April 15, 2003';
$pattern = '/(\w+) (\d+), (\d+)/i';
$replacement = '${1}1,$3';
echo preg_replace($pattern, $replacement, $string);
?>
以上例程会输出:
April1,2003
Example #2 preg_replace()中使用基于索引的数组
<?php
$string = 'The quick brown fox jumped over the lazy dog.';
$patterns = array();
$patterns[0] = '/quick/';
$patterns[1] = '/brown/';
$patterns[2] = '/fox/';
$replacements = array();
$replacements[2] = 'bear';
$replacements[1] = 'black';
$replacements[0] = 'slow';
echo preg_replace($patterns, $replacements, $string);
?>
以上例程会输出:
The bear black slow jumped over the lazy dog.
对模式和替换内容按key进行排序我们可以得到期望的结果。
<?php
ksort($patterns);
ksort($replacements);
echo preg_replace($patterns, $replacements, $string);
?>
以上例程会输出:
The slow black bear jumped over the lazy dog.
Example #3 替换一些值
<?php
$patterns = array ('/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/',
'/^\s*{(\w+)}\s*=/');
$replace = array ('\3/\4/\1\2', '$\1 =');
echo preg_replace($patterns, $replace, '{startDate} = 1999-5-27');
?>
以上例程会输出:
$startDate = 5/27/1999
Example #4 剥离空白字符
这个例子剥离多余的空白字符
<?php
$str = 'foo o';
$str = preg_replace('/\s\s+/', ' ', $str);
// 将会改变为'foo o'
echo $str;
?>
Example #5 使用参数count
<?php
$count = 0;
echo preg_replace(array('/\d/', '/\s/'), '*', 'xp 4 to', -1 , $count);
echo $count; //3
?>
以上例程会输出:
xp***to 3
注释 ¶
Note:
当使用数组形式的
pattern
和replacement
时, 将会按照key在数组中出现的顺序进行处理. 这不一定和数组的索引顺序一致. 如果你期望使用索引对等方式用replacement
对pattern
进行替换, 你可以在调用preg_replace()之前对两个数组各进行一次ksort()排序.
参见 ¶
- PCRE 模式
- preg_filter() - 执行一个正则表达式搜索和替换
- preg_match() - 执行一个正则表达式匹配
- preg_replace_callback() - 执行一个正则表达式搜索并且使用一个回调进行替换
- preg_split() - 通过一个正则表达式分隔字符串
- preg_last_error() - 返回最后一个PCRE正则执行产生的错误代码
preg_replace_callback
(PHP 4 >= 4.0.5, PHP 5)
preg_replace_callback — 执行一个正则表达式搜索并且使用一个回调进行替换
说明 ¶
$pattern
, callable $callback
, mixed $subject
[, int $limit
= -1 [, int &$count
]] )这个函数的行为除了 可以指定一个 callback
替代 replacement
进行替换 字符串的计算,其他方面等同于preg_replace()。
参数 ¶
pattern
-
要搜索的模式,可以使字符串或一个字符串数组。
callback
-
一个回调函数,在每次需要替换时调用,调用时函数得到的参数是从
subject
中匹配到的结果。回调函数返回真正参与替换的字符串。这是该回调函数的签名:string handler ( array$matches
)你可能经常会需要
callback
函数而 仅用于preg_replace_callback()一个地方的调用。在这种情况下,你可以 使用匿名函数来定义一个匿名函数作 为preg_replace_callback()调用时的回调。 这样做你可以保留所有 调用信息在同一个位置并且不会因为一个不在任何其他地方使用的回调函数名称而污染函数名称空间。Example #1 preg_replace_callback() 和 匿名函数
<?php
/* 一个unix样式的命令行过滤器,用于将段落开始部分的大写字母转换为小写。 */
$fp = fopen("php://stdin", "r") or die("can't read stdin");
while (!feof($fp)) {
$line = fgets($fp);
$line = preg_replace_callback(
'|<p>\s*\w|',
function ($matches) {
return strtolower($matches[0]);
},
$line
);
echo $line;
}
fclose($fp);
?> subject
-
要搜索替换的目标字符串或字符串数组。
limit
-
对于每个模式用于每个
subject
字符串的最大可替换次数。 默认是-1(无限制)。 count
-
如果指定,这个变量将被填充为替换执行的次数。
返回值 ¶
如果subject
是一个数组, preg_replace_callback()返回一个数组,其他情况返回字符串。 错误发生时返回 NULL
。
如果查找到了匹配,返回替换后的目标字符串(或字符串数组), 其他情况subject
将会无变化返回。
更新日志 ¶
版本 | 说明 |
---|---|
5.1.0 | 增加了参数count 。 |
范例 ¶
Example #2 preg_replace_callback()示例
<?php
// 将文本中的年份增加一年.
$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
Example #3 preg_replace_callback()使用递归构造处理BB码的封装
<?php
$input = "plain [indent] deep [indent] deeper [/indent] deep [/indent] plain";
function parseTagsRecursive($input)
{
/* 译注: 对此正则表达式分段分析
* 首尾两个#是正则分隔符
* \[indent] 匹配一个原文的[indent]
* ((?:[^[]|\[(?!/?indent])|(?R))+)分析:
* (?:[^[]|\[(?!/?indent])分析:
* 首先它是一个非捕获子组
* 两个可选路径, 一个是非[字符, 另一个是[字符但后面紧跟着不是/indent或indent.
* (?R) 正则表达式递归
* \[/indent] 匹配结束的[/indent]
* /
$regex = '#\[indent]((?:[^[]|\[(?!/?indent])|(?R))+)\[/indent]#';
if (is_array($input)) {
$input = '<div style="margin-left: 10px">'.$input[1].'</div>';
}
return preg_replace_callback($regex, 'parseTagsRecursive', $input);
}
$output = parseTagsRecursive($input);
echo $output;
?>
参见 ¶
- PCRE 模式
- preg_replace() - 执行一个正则表达式的搜索和替换
- preg_last_error() - 返回最后一个PCRE正则执行产生的错误代码
- 匿名函数
- callback 类型的信息