phpdateescapingpreg-replacepreg-match

Escape plain text characters in a string which includes a date format expression to be passed into a date rendering function


I'm trying to escape every single character wrapped in {{ and }} in a string so this:

d-m-Y {{warning}}

Becomes this:

d-m-Y \{\{\w\a\r\n\i\n\g\}\}

I'm trying to achieve it using preg_replace:

$int = preg_match_all('/(\{\{.*?\}\})/', $format, $matches, PREG_SET_ORDER);
if( $int )
{
    $to_replace = preg_replace('/(.+?)/', "\\$1", $matches[0][0]);
    $format = str_replace( $matches[0][0], $to_replace, $format );
}

But the replace function converts it to $1$1$1$1$1$1$1$1$1$1$1, I'm obviously doing something wrong here.


Solution

  • Basically \\$1 should become \\\$1 in your pattern.

    However, you can use preg_replace_callback() here:

    $string = 'd-m-Y {{warning}}';
    
    echo preg_replace_callback('/\{\{.*?\}\}/', function($match) {
        return preg_replace('/./', '\\\$0', $match[0]);
    }, $string);
    

    Output:

    d-m-Y \{\{\w\a\r\n\i\n\g\}\}
    

    During tests, I found out that there is even a faster way to replace the characters in the callback function than preg_replace(). You can use wordwrap():

    echo preg_replace_callback('/\{\{.*?\}\}/', function($match) {
        return wordwrap($match[0], 1, '\\', true);
    }, $string);
    

    This will work ~15 % faster than the above attempt.