php中的模式修饰符 二
在 php中的模式修饰符一 中我们介绍了 i
,m
,s
和 x
几个修饰符,本篇我们继续介绍。
e
(PREG_REPLACE_EVAL)
该修饰符已经被PHP7版本弃用了。如果设置了修饰符, preg_replace() 在进行了对替换字符串的 后向引用替换之后, 将替换后的字符串作为php 代码评估执行(eval 函数方式),并使用执行结果 作为实际参与替换的字符串。单引号、双引号、反斜线()和 NULL 字符在 后向引用替换时会被用反斜线转义。
<?php
$str = "<p>This is an example</p>";
$pattern = "/^<p>(.*)<\/p>$/e";
$str = preg_replace($pattern,"add_tr('\\1')",$str);
var_dump($str);
function add_tr($str)
{
return "<tr>$str</tr>";
}
这里要使用 php5+ 版本来执行,而不能使用php7 版本。执行结果
string(27) "<tr>This is an example</tr>"
注意,对于 php5 高版本的会出现提示说该修饰符已经被降级
PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /Users/liuhanzeng/workspace/php/reg.php on line 7
Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /Users/liuhanzeng/workspace/php/reg.php on line 7
string(27) "<tr>This is an example</tr>"
如果不指定e
, $pattern = '/^<p>(.*)<\/p>$/'
那结果就成了 add_tr('This is an example')
。也就是不能使用回调函数了,直接当成字符串去把目标字符串替换掉。
如果说设置了e
之后是使用回调函数的话,这种说法是不正确的。而是将preg_replace函数的第二个参数使用eval()
函数来执行,然后将执行后的结果替换掉目标字符串。 下面再举几个例子来说明
<?php
$str = "<p>This is an example</p>";
$pattern = "/^<p>(.*)<\/p>$/e";
$str = preg_replace($pattern,"\\1",$str);
当匹配成功以后,\\1
是捕获的第一个子组的内容——This is an example
。 设置了e
,就会将\\1
用eval
函数执行。所以就会报错
Fatal error: preg_replace(): Failed evaluating code:
This is an example in ...
因为This is an example
不是一段有效的PHP代码。
注意,因为我们在preg_replace中给的第二个参数是
\\1
,所以在eval看来This is an example
并不是一个字符串。如果我们给的第二个参数是'\\1'
,那在eval看来是这样的'This is an example'
。所以就不会报错。 看例子
<?php
$str = "<p>This is an example</p>";
$pattern = "/^<p>(.*)<\/p>$/e";
$str = preg_replace($pattern,"'\\1'",$str);
var_dump($str);
正确替换了目标字符串
string(18) "This is an example"
所以说我们回过头来再看下面这个例子
<?php
$str = "<p>This is an example</p>";
$pattern = "/^<p>(.*)<\/p>$/e";
$str = preg_replace($pattern,"add_tr('\\1')",$str);
var_dump($str);
function add_tr($str)
{
return "<tr>$str</tr>";
}
仔细看的话发现这种形式并不是严格意义上的指定一个回调函数,它就是一个对函数的调用代码。因为通常的指定回调函数是不能加小括号()
的。
由于e
在PHP7
中已经被废弃了,所以要想使用上面那种回调函数,可以用preg_replace_callback
来代替。
<?php
$str = "<p>This is an example</p>";
$pattern = "/^<p>(.*)<\/p>$/";
$str = preg_replace_callback($pattern,function ($matches) {
return add_tr($matches[1]);
},$str);
var_dump($str);
function add_tr($str)
{
return "<tr>$str</tr>";
}
使用PHP7执行结果就正常了
string(27) "<tr>This is an example</tr>"
注意:在
function($matches){}
中最后一定要有return
。
通过上面preg_replace_callback
的回调函数,然后对比之前例子中使用e
指定的回调函数,发现形式是不是不一样的。
其实,是不是可以认为e
就是使用的eval
的第一个字符。就是为了对preg_replace
第二个参数使用eval
函数执行。由此也知道,e
只是在使用preg_replace函数的时候设置,其他函数和它就没有关系了。
由于eval函数是存在很大的风险的,容易造成远程执行任何代码。所以不推荐使用。 这也是为什么废弃它的原因。