Marko
Marko

Reputation: 213

Replace all substring instances with a variable string

If you had the string

'Old string Old more string Old some more string'

and you wanted to get

'New1 string New2 more string New3 some more string'

how would you do it?

In other words, you need to replace all instances of 'Old' with variable string 'New'.$i. How can it be done?

Upvotes: 6

Views: 7925

Answers (5)

hakre
hakre

Reputation: 197659

I had some similar solution like KingCrunch's, but as he already answered it, I was wondering about a str_replace variant with a callback for replacements and came up with this (Demo):

$subject = array('OldOldOld', 'Old string Old more string Old some more string');
$search = array('Old', 'string');
$replace = array(
    function($found, $count) {return 'New'.$count;},
    function($found, $count) {static $c=0; return 'String'.(++$c);}
);
$replace = array();

print_r(str_ureplace($search, $replace, $subject));

/**
 * str_ureplace
 *
 * str_replace like function with callback
 *
 * @param string|array search
 * @param callback|array $replace
 * @param string|array $subject
 * @param int $replace_count
 * @return string|array subject with replaces, FALSE on error.
 */
function str_ureplace($search, $replace, $subject, &$replace_count = null) {
    $replace_count = 0;

    // Validate input
    $search = array_values((array) $search);
    $searchCount = count($search);
    if (!$searchCount) {
        return $subject;
    }
    foreach($search as &$v) {
        $v = (string) $v;
    }
    unset($v);
    $replaceSingle = is_callable($replace);
    $replace = $replaceSingle ? array($replace) : array_values((array) $replace);
    foreach($replace as $index=>$callback) {
        if (!is_callable($callback)) {
            throw new Exception(sprintf('Unable to use %s (#%d) as a callback', gettype($callback), $index));
        }
    }

    // Search and replace
    $subjectIsString = is_string($subject);
    $subject = (array) $subject;
    foreach($subject as &$haystack) {
        if (!is_string($haystack)) continue;
        foreach($search as $key => $needle) {
            if (!$len = strlen($needle))
                continue;
            $replaceSingle && $key = 0;
            $pos = 0;
            while(false !== $pos = strpos($haystack, $needle, $pos)) {
                $replaceWith = isset($replace[$key]) ? call_user_func($replace[$key], $needle, ++$replace_count) : '';
                $haystack = substr_replace($haystack, $replaceWith, $pos, $len);
            }
        }
    }
    unset($haystack);

    return $subjectIsString ? reset($subject) : $subject;
}

Upvotes: 1

Toto
Toto

Reputation: 91385

Use:

$str = 'Old string Old more string Old some more string';
$i = 1;
while (preg_match('/Old/', $str)) {
    $str = preg_replace('/Old/', 'New'.$i++, $str, 1);
}
echo $str,"\n";

Output:

New1 string New2 more string New3 some more string

Upvotes: 1

KingCrunch
KingCrunch

Reputation: 131841

An iterative solution that doesn't need regular expressions:

$str = 'Old string Old more string Old some more string';
$old = 'Old';
$new = 'New';

$i = 1;

$tmpOldStrLength = strlen($old);

while (($offset = strpos($str, $old, $offset)) !== false) {
  $str = substr_replace($str, $new . ($i++), $offset, $tmpOldStrLength);
}

$offset in strpos() is just a little bit micro-optimization. I don't know, if it's worth it (in fact I don't even know, if it changes anything), but the idea is that we don't need to search for $old in the substring that is already processed.

See Demo

Old string Old more string Old some more string
New1 string New2 more string New3 some more string

Upvotes: 6

Ovais Khatri
Ovais Khatri

Reputation: 3211

From the PHP manual on str_replace:

Replace all occurrences of the search string with the replacement string

mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

search

The value being searched for, otherwise known as the needle. An array may be used to designate multiple needles.

replace

The replacement value that replaces found search values. An array may be used to designate multiple replacements.

subject

The string or array being searched and replaced on, otherwise known as the haystack.

If subject is an array, then the search and replace is performed with every entry of subject, and the return value is an array as well.

count

If passed, this will be set to the number of replacements performed.

Upvotes: 1

Ilya Boyandin
Ilya Boyandin

Reputation: 3099

Use preg_replace_callback.

$count = 0;
$str = preg_replace_callback(
    '~Old~',
    create_function('$matches', 'return "New".$count++;'),
    $str
);

Upvotes: 2

Related Questions