PHP preg_replace_callback()和带有eval()的create_function()不起作用


PHP preg_replace_callback() and create_function() with eval() do not work

我正试图在互联网上部署我的网站,以便在真实环境中进行测试。它是某种文本编辑器,用户可以在其中使用正则表达式和用户定义的回调函数。

我对preg_replace_callback()函数有一些问题。我的宿主的PHP版本早于5.3,我不能在代码中使用匿名函数(我在localhost上有PHP 5.4)。因此,我必须重写这部分代码(它在localhost上正常工作)

$newString = preg_replace_callback(
                    '#' . $this->pattern . '#' . $this->modifiers,
                    function($match)
                    {
                        return eval('return ' . $this->replacement . ';');
                    },
                    $string);

在这一点上,我不是在谈论使用eval()的危险-这个问题稍后会得到适当的关注("禁止"单词列表检查等)

$replacement = $this->replacement;
$newString = preg_replace_callback(
    '#' . $this->pattern . '#' . $this->modifiers,
    create_function('$match', '
                     global $replacement;
                     return eval(''return '' . $replacement . '';'');
                    '),
                    $string);

不起作用,也不会出现错误。我的代码出了什么问题?

任何帮助都将不胜感激。


新信息。我试过这个

 Class A
{
    public function check()
    {
        $string = 'series 3-4';
        $pattern = 'series[ ]*('d+)[ ]*-[ ]*('d+)';
        $modifiers = 'um';
        $replacement = '$match[2] == $match[1] + 1 ? "series $match[1] and $match[2]" : "series $match[1]-$match[2]"';
        $newString = preg_replace_callback(
                            '#' . $pattern . '#' . $modifiers,
                            create_function('$match', '
                             global $replacement;
                             echo $replacement;
                             return eval(''return '' . $replacement . '';'');
                            '),
                            $string);
        echo $newString;
    }
}
$a = new A;
$a->check();//get nothing

并发现create_function()中的$replacement为空。但是当我在类外使用相同的create_function()时,$replacement不为空:

$string = 'series 3-4';
$pattern = 'series[ ]*('d+)[ ]*-[ ]*('d+)';
$modifiers = 'um';
$replacement = '$match[2] == $match[1] + 1 ? "series $match[1] and $match[2]" : "series $match[1]-$match[2]"';
$newString = preg_replace_callback(
                '#' . $pattern . '#' . $modifiers,
                create_function('$match', '
                 global $replacement;
                 echo $replacement . "<br/>";
                 return eval(''return '' . $replacement . '';'');
                '),
                $string);
echo $newString;
//$match[2] == $match[1] + 1 ? "series $match[1] and $match[2]" : "series $match[1]-$match[2]"
//series 3 and 4

您可以使用一个方法来代替lambda函数:

Class A
{
    private $replacement;
    public function check()
    {
        $string = 'series 3-4';
        $pattern = 'series[ ]*('d+)[ ]*-[ ]*('d+)';
        $this->replacement = '$match[2] == $match[1] + 1 ? "series $match[1] and $match[2]" : "series $match[1]-$match[2]"';
        $modifiers = 'um';
        $newString = preg_replace_callback(
                            '#' . $pattern . '#' . $modifiers,
                            array($this, 'replacementCallback'),
                            $string);
        echo $newString;
    }
    private function replacementCallback($match)
    {
        return eval('return ' . $this->replacement . ';');
    }
}
$a = new A;
$a->check();

这是有效的,将正确格式化为PHP源的$replacement字符串值插入函数的源中:

function check()
{
    $string = 'series 3-4';
    $pattern = 'series[ ]*('d+)[ ]*-[ ]*('d+)';
    $modifiers = 'um';
    $replacement = '$match[2] == $match[1] + 1 ? "series $match[1] and $match[2]" : "series $match[1]-$match[2]"';
    $newString = preg_replace_callback(
                        '#' . $pattern . '#' . $modifiers,
                        create_function('$match', '
                            return eval("return " . '.var_export($replacement,true).' . ";");
                        '),
                        $string);
    echo $newString;
}
check(); // prints "series 3 and 4"
?>

但是,既然你可以直接把它放在函数的源代码中:,为什么还要麻烦输入代码并eval

<?
function check()
{
    $string = 'series 3-4';
    $pattern = 'series[ ]*('d+)[ ]*-[ ]*('d+)';
    $modifiers = 'um';
    $replacement = '$match[2] == $match[1] + 1 ? "series $match[1] and $match[2]" : "series $match[1]-$match[2]"';
    $newString = preg_replace_callback(
                        '#' . $pattern . '#' . $modifiers,
                        create_function('$match', '
                            return '.$replacement.';
                        '),
                        $string);
    echo $newString;
}
check(); // prints "series 3 and 4"
?>