来自多遍搜索和替换的不需要的替换



我试图使用PHP来替换JSON中的一些项目id,并遇到一个问题,其中第一次传递的替换被第二次传递的替换覆盖。

<?php
$body = "Hello World";
$soul = str_replace(['World', 'Earth'], ['Earth', 'Vietnam'], $body);
echo $soul;

期望:"你好地球"观察到"你好越南">

我的情况更残酷,因为我的映射是数字到数字的映射,如"id139"=>"id189"one_answers"id189"=; id18"。如何在一大块文本中进行搜索和替换而不冒多次替换的风险?

我们得到的最接近好的解决方案是这样的:

$regPatterns = [
"/floatingSectionItems-(d+)-1006/",
"/floatingSectionItems-(d+)-160/",
"/floatingSectionItems-(d+)-1/",
];
$regReplacements = [
"goosebumps-160-160",
"goosebumps-168-168",
"goosebumps-171-171",
];
$layout = preg_replace($regPatterns, $regReplacements, $layout);
$layout = str_replace(‘goosebumps’, ‘floatingSectionItems’, $layout);

虽然在这种特殊情况下有效,但我觉得可能存在不需要五次传递的解决方案;比如preg_match_all(),后面跟着有限的str_replace(),或者是一种一次性解析原始内容并进行替换的方法。

我认为您可能需要尝试找出如何构建一个单一的模式正则表达式,它可以潜在地与您的自定义替换逻辑的回调一起工作,以便该模式不会在先前的替换上进行处理。

$layout = " blah blah floatingSectionItems-100-200 floatingSectionItems-300-400 blah blah ";
$layout = preg_replace_callback('/floatingSectionItems-(d+)-(d+)/', function($matches){
if( $matches[1] == '100' and $matches[2] == '200' )
{
return 'floatingSectionItems-300-400';
}
if( $matches[1] == '300' and $matches[2] == '400' )
{
return 'floatingSectionItems-100-200';
}
return $matches[0]; // do nothing
}, $layout);
echo $layout;

然后你可以在回调中构建你的替换逻辑,每次只处理一个项目,并且永远不会在已经替换的项目上回溯,在这个例子中,我翻转了两个数字模式,以显示它不会冲突。

捕获组(括号)将允许您只处理模式的数字值。


此外,如果您希望将替换作为数组注入回调中,您可以使用use($foo)

的函数语法来完成此操作
$replacements = [ '100' => '300', '300' => '100' ];
$layout = preg_replace_callback('/floatingSectionItems-(d+)-(d+)/', function($matches) use ($replacements){
if( isset( $replacements[ $matches[1] ] ) )
return sprintf('floatingSectionItems-%s-200', $replacements[ $matches[1] ] );
return $matches[0];
}, $layout);

您可以使用strtr ():

$body = "Hello World";
echo strtr(
$body,
[
'World' => 'Earth',
'Earth' => 'Vietnam'
]
);
Hello Earth

将首先尝试最长的键。一旦子字符串被替换,它的新值将不再被搜索。

最新更新