在php's preg_replace中避免反向引用替换


Avoid backreference replacement in php's preg_replace

考虑以下使用preg_replace

$str='{{description}}';
$repValue='$0.0 $00.00 $000.000 $1.1 $11.11 $111.111';
$field = 'description';
$pattern = '/{{'.$field.'}}/';
$str =preg_replace($pattern, $repValue, $str );
echo $str;

// Expected output: $0.0 $00.00 $000.000 $1.1 $11.11 $111.11
// Actual output:   {{description}}.0 {{description}}.00 {{description}}0.000 .1 .11 1.111 

这是一个显示问题的phpFiddle

我很清楚,实际输出不像预期的那样,因为preg_replace$0, $0, $0, $1, $11, and $11视为匹配组的反向引用,将$0替换为完整匹配,$1 and $11替换为空字符串,因为没有捕获组1或11。

如何防止preg_replace将替换值中的价格视为回引用并试图填充它们?

注意$repValue是动态的,它的内容在操作之前是不知道的。

在使用字符转换(strtr)之前转义美元字符:

$repValue = strtr('$0.0 $00.00 $000.000 $1.1 $11.11 $111.111', ['$'=>''$']);

对于更复杂的情况(使用美元和转义的美元),您可以执行这种替换(这次完全防水):

$str = strtr($str, ['%'=>'%%', '$'=>'$%', ''''=>'''%']);
$repValue = strtr($repValue, ['%'=>'%%', '$'=>'$%', ''''=>'''%']);
$pattern = '/{{' . strtr($field, ['%'=>'%%', '$'=>'$%', ''''=>'''%']) . '}}/';
$str = preg_replace($pattern, $repValue, $str );
echo strtr($str, ['%%'=>'%', '$%'=>'$', '''%'=>'''']);

注意:如果$field只包含字面值字符串(不是子模式),则不需要使用preg_replace。你可以使用str_replace代替,在这种情况下,你不需要替换任何东西。