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

时间:2016-10-10 23:34:33

标签: php regex preg-replace pcre

考虑以下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 showing the issue

我很清楚实际输出不符合预期,因为preg_replace正在查看$0, $0, $0, $1, $11, and $11作为匹配组的后向参考,并将$0替换为完全匹配,$1 and $11使用空字符串,因为没有捕获组1或11。

如何阻止preg_replace将替换值中的价格视为反向引用并尝试填充它们?

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

1 个答案:

答案 0 :(得分:5)

在使用字符翻译(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代替,在这种情况下,您无需替换任何内容。