避免在 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
代替,在这种情况下您不必替换任何东西。
考虑下面对 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
代替,在这种情况下您不必替换任何东西。