【问题标题】:PHP preg_replace_callback() and create_function() with eval() do not workPHP preg_replace_callback() 和 create_function() 与 eval() 不起作用
【发布时间】:2012-08-25 09:49:29
【问题描述】:

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

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

$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

【问题讨论】:

    标签: php oop eval preg-replace-callback create-function


    【解决方案1】:

    您可以使用方法代替 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();
    

    【讨论】:

    • iirc 回调应该是public
    • 我在发布之前执行了代码。 PHP 5.3.13。编辑:刚刚检查了 5.2.17。也可以。
    • @zerkms 使用私有回调在 PHP 7 中运行良好,不确定 5+ 是否对此有任何问题。
    【解决方案2】:

    这可行,将正确格式化为 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"
    ?>
    

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

    <?
    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"
    ?>
    

    【讨论】:

    • 是的,真的。现在我看到我根本不必使用 eval() 。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2013-03-17
    • 1970-01-01
    相关资源
    最近更新 更多