2

実際の環境でテストするために、Web サイトをインターネット上に展開しようとしています。これは、ユーザーが正規表現とユーザー定義のコールバック関数を使用できる、ある種のテキスト エディターです。

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
4

2 に答える 2

5

ラムダ関数の代わりにメソッドを使用できます。

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();
于 2012-08-25T11:33:31.227 に答える
1

これ$replacementは機能し、PHPソースとして適切にフォーマットされた文字列値を関数のソースに挿入します。

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"
?>
于 2012-08-26T08:43:19.580 に答える