3

I have a script that generates content containing certain tokens, and I need to replace each occurrence of a token, with different content resulting from a separate loop.

It's simple to use str_replace to replace all occurrences of the token with the same content, but I need to replace each occurrence with the next result of the loop.

I did see this answer: Search and replace multiple values with multiple/different values in PHP5?

however it is working from pre-defined arrays, which I don't have.

Sample 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.

I need to replace each occurrence of %%token%% with content generated, for argument's sake, by this simple loop:

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

So replace each %%token%% with a different random number value $token.

Is this something simple that I'm just not seeing?

Thanks!

3
  • I don't think there is a library function to do this for you. You'll just have to code up the search and replace yourself. Commented Sep 25, 2011 at 6:03
  • I'm aware of that, I'm looking for help with it. I haven't been able to wrap my head around a solution for this. My skill with preg_replace isn't so great, but I found something that looked helpful, but I couldn't figure out how to modify it for my needs: $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); Commented Sep 25, 2011 at 6:22
  • Sorry, misunderstood the issue. See answer. Commented Sep 25, 2011 at 6:39

4 Answers 4

5

I don't think you can do this using any of the search and replace functions, so you'll have to code up the replace yourself.

It looks to me like this problem works well with explode(). So, using the example token generator you provided, the solution looks like this:

$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);
}
Sign up to request clarification or add additional context in comments.

3 Comments

Yep this was about the closest solution I had personally come up with, though I was really hoping maybe it could be done with some sort of preg_replace wizardry of some kind. Maybe I'll just have to go the explode route after all. Let me play with this and see if I can get it to do the job. Appreciate the help very much!
You could use preg_match in place of explode, but the result would be more complicated. :/
Well hot damn... this solution worked perfectly out of the gate. I had thought of this basic approach before but for some reason thought it would be a total mess to handle this way. I shoulda just gone with my instincts. =) Thanks for the help!!
3

I know this is an old thread, but I stumbled across it while trying to achieve something similar. If anyone else sees this, I think this is a little nicer:

Create some sample text:

$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.";

Find the search string with regex:

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

Define a callback function to change the matches

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

Echo the results:

echo $new_text;

So as a function set:

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

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

Comments

2

I had a similar issue where I had a file that I needed to read. It had multiple occurrences of a token, and I needed to replace each occurrence with a different value from an array.

This function will replace each occurrence of the "token"/"needle" found in the "haystack" and will replace it with a value from an indexed array.

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;
}

By the way, 'mostr_replace' is short for "Multiple Occurrence String Replace".

1 Comment

I would suggest an improvement, find the count once and just run through the string. substr_count is a bit too expensive to run it each time.
1

You can use the following code:

$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);
    }
}

1 Comment

Helpful but not quite there yet: $content = substr($content, 0,$pos) . $token . substr($content, $pos + strlen($needle));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.