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

标签 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 和 $11 查看为匹配的反向引用组将 $0 替换为完全匹配项,将 $1 和 $11 替换为空字符串,因为没有捕获组 1 或 11。

如何防止 preg_replace 将重置值(value)中的价格视为反向引用并尝试填充它们?

请注意,$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 来代替,在这种情况下您不必替换任何内容。

关于php - 避免在 php 的 preg_replace 中进行反向引用替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39968330/

相关文章:

php - "$foo = 5 && $bar = 15"是如何评估的,为什么它不是错误?

php - 将数百万行从一个 mysql 表迁移到另一个作为 Laravel 5 中的副本

php - 为什么我不能从 PHP 中选择 MySQL 数据库?我得到 "access denied"

PHP 和 Money,将钱转换为美分

regex - 使用 grep 查询选择性文件

ruby - 如何获取字符串中所有出现的模式的索引

php - 如何用正则表达式替换具有相同字符数的多个字符?

php - 从字符串中删除非文本字符(如表情符号)

php - 使用 preg_replace 缩小 CSS

javascript - 正则表达式对 javascript block 注释执行全局匹配