用不同的值替换字符串的多个出现次数

3
我有一个脚本,用于生成包含特定令牌的内容,并且我需要替换每个令牌的每个出现,以不同的内容结果替换来自单独循环的内容。
使用str_replace很容易将所有令牌的所有出现替换为相同的内容,但是我需要用循环的下一个结果替换每个出现的令牌。
我看到了这个答案:Search and replace multiple values with multiple/different values in PHP5?,但它是使用预定义数组工作的,而我没有这些数组。
示例内容:
This is an example of %%token%% that might contain multiple instances of a particular
%%token%%, that need to each be replaced with a different piece of %%token%% generated 
elsewhere.

我需要将每个%%token%%替换为由以下简单循环生成的内容:

for($i=0;$i<3;$i++){
    $token = rand(100,10000);
}

所以将每个%%token%%替换为不同的随机数值$token。

这是我没看到的简单问题吗?

谢谢!


我认为没有一个库函数可以为您完成这个任务。您只能自己编写搜索和替换的代码。 - Ryan Ballantyne
我知道这一点,我正在寻求帮助。我还没有能够想出解决方案。我的preg_replace技能不是很好,但我找到了一些看起来有用的东西,但我无法弄清如何修改它以满足我的需求:$string = 'Time for some foo, because it is foo we want and foo we will get. Time for some foo, because it is foo we want and foo we will get.'; $replaceme = 'foo'; $replacewith = 'bar'; $nthtimes = 2; echo preg_replace("/((.*?)(".$replaceme.")){".$nthtimes."}/e", '(preg_replace("/".$replaceme."$/", "", "\0")).$replacewith', $string); - JVC
抱歉,误解了问题。请看答案。 - Ryan Ballantyne
4个回答

5

我认为你无法使用任何搜索和替换函数来完成这个任务,所以你必须自己编写替换代码。

在我看来,这个问题很适合使用explode()。因此,使用你提供的示例令牌生成器,解决方案如下:

$shrapnel = explode('%%token%%', $str);
$newStr = '';
for ($i = 0; $i < count($shrapnel); ++$i)  {
    // The last piece of the string has no token after it, so we special-case it
    if ($i == count($shrapnel) - 1)
        $newStr .= $shrapnel[$i];
    else
        $newStr .= $shrapnel[$i] . rand(100,10000);
}

对于这个问题,我自己设计的解决方案可能是最接近的,尽管我真的希望用某种 preg_replace 魔法来完成。也许最后还是得使用 explode 方法吧。让我试一试,看能否达到预期的效果。非常感谢你的帮助! - JVC
你可以使用 preg_match 代替 explode,但结果会更加复杂。 :/ - Ryan Ballantyne
哇塞...这个解决方案一开始就完美地运作了。我之前想过这种基本的方法,但出于某种原因,我认为用这种方式处理会非常混乱。我应该听从自己的直觉。=)感谢您的帮助!! - JVC

2

我有一个类似的问题,需要读取一个文件。它在多个位置包含相同的标记,我需要使用来自索引数组的不同值替换每个出现的标记。

该函数将替换"haystack"中找到的每个"token"/"needle"的出现,并用来自索引数组的值进行替换。

function mostr_replace($needle, $haystack, $replacementArray, $needle_position = 0, $offset = 0)
{
    $counter = 0;
    while (substr_count($haystack, $needle)) {

        $needle_position = strpos($haystack, $needle, $offset);
        if ($needle_position + strlen($needle) > strlen($haystack)) {
            break;
        }
        $haystack = substr_replace($haystack, $replacementArray[$counter], $needle_position, strlen($needle));
        $offset = $needle_position + strlen($needle);
        $counter++;
    }

    return $haystack;
}

顺便说一下,“mostr_replace”是“多次出现字符串替换”的缩写。


我建议一种改进方法,先找到计数,然后只需遍历字符串即可。substr_count 每次运行都有点太昂贵了。 - v010dya

2

我知道这是一个旧的帖子,但在尝试达到类似目标时,我偶然发现了它。如果其他人看到了这个帖子,我认为这个方法更好一些:

创建一些示例文本:

$text="This is an example of %%token%% that might contain multiple instances of a particular
%%token%%, that need to each be replaced with a different piece of %%token%% generated 
elsewhere.";

使用正则表达式查找搜索字符串:

$new_text = preg_replace_callback("|%%token%%|", "_rand_preg_call", $text);

定义一个回调函数来改变匹配项

function _rand_preg_call($matches){
  return rand(100,10000);
}

回显结果:
echo $new_text;

作为一个函数集:

function _preg_replace_rand($text,$pattern){
  return preg_replace_callback("|$pattern|", "_rand_preg_call", $text);
}

function _rand_preg_call($matches){
  return rand(100,10000);
}

1
你可以使用以下代码:
$content = "This is an example of %%token%% that might contain multiple instances of a particular %%token%%, that need to each be replaced with a different piece of %%token%% generated elsewhere.";

while (true)
{
    $needle = "%%token%%";
    $pos = strpos($content, $needle);
    $token = rand(100, 10000);
    if ($pos === false)
    {
        break;
    }
    else
    {
        $content = substr($content, 0,
                          $pos).$token.substr($content, $pos + strlen($token) + 1);
    }
}

有帮助但还不够完美:$content = substr($content, 0,$pos) . $token . substr($content, $pos + strlen($needle)); - 111

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接