避免在 php 的 preg_replace 中进行反向引用替换

Avoid backreference replacement in php's preg_replace

考虑下面对 preg_replace

的使用
$str='{{description}}';
$repValue='[=12=].0 [=12=].00 [=12=]0.000 .1 .11 1.111';

$field = 'description';
$pattern = '/{{'.$field.'}}/';

$str =preg_replace($pattern, $repValue, $str );
echo $str;


// Expected output: [=12=].0 [=12=].00 [=12=]0.000 .1 .11 1.11
// Actual output:   {{description}}.0 {{description}}.00 {{description}}0.000 .1 .11 1.111 

这是一个phpFiddle showing the issue

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

如何防止 preg_replace 将我的重置价值中的价格视为反向参考并尝试填充它们?

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

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

$repValue = strtr('[=10=].0 [=10=].00 [=10=]0.000 .1 .11 1.111', ['$'=>'$']);

对于更复杂的情况(有美元和转义美元)你可以做这种替换(这次完全防水):

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

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