views:

152

answers:

2

I am trying to achieve the following:

$subject = 'a b a';
$search = 'a';
$replace = '1';

Desired result:

Array
(
[0] => 1 b a
[1] => a b 1
)

Is there any way of achieving this with preg_replace?

preg_replace('/\b'.$search.'(?=\s+|$)/u', $replace, array($subject));

will return all the replacments in the same result:

Array
(
[0] => 1 b 1
)

Cheers

+1  A: 

I think it is not possible. You can specify a limit of replacements in the optional fourth parameter, but that always starts at the beginning.

It could be possible to achieve what you're looking for with preg_split(). You would just have to split your string on all occasions of your search pattern and then mess with them one by one. If your search pattern is just a simple string, you can achieve the same with explode(). If you need help figuring this approach out, I'll be happy to help.

EDIT: Let's see if this works for you:

$subject = 'a b a';
$pattern = '/a/';
$replace = 1;

// We split the string up on all of its matches and obtain the matches, too
$parts = preg_split($pattern, $subject);
preg_match_all($pattern, $subject, $matches);

$numParts = count($parts);
$results = array();

for ($i = 1; $i < $numParts; $i++)
{
    // We're modifying a copy of the parts every time
    $partsCopy = $parts;

    // First, replace one of the matches
    $partsCopy[$i] = $replace.$partsCopy[$i];

    // Prepend the matching string to those parts that are not supposed to be replaced yet
    foreach ($partsCopy as $index => &$value)
    {
        if ($index != $i && $index != 0)
            $value = $matches[0][$index - 1].$value;
    }

    // Bring it all back together now
    $results[] = implode('', $partsCopy);
}

print_r($results);

Note: This is not tested yet. Please report whether it works.

EDIT 2:

I tested it with your example now, fixed a few things and it works now (at least with that example).

Franz
Did this not work for you?
Franz
+1  A: 
function multipleReplace($search,$subject,$replace) {
    preg_match_all($search, $subject,$matches,PREG_OFFSET_CAPTURE);
    foreach($matches as $match) {
    if (is_array($match)) {
        foreach ($match as $submatch) {
     list($string,$start) = $submatch;
     $length = strlen($string);
     $val = "";
     if ($start - 1 > 0) {
         $val .= substr($subject,0,$start);
     }
     $val .= preg_replace($search,$string,$replace);
     $val .= substr($subject,$start + $length);
     $ret[] = $val;
        }
    }
    }
    return $ret;
}

$search = 'a';

print_r(multipleReplace('/\b'.$search.'(?=\s+|$)/u','a b a','1'));

Output

Array
(
    [0] => 1 b a
    [1] => a b 1
)
Peter Lindqvist
This would not always work as replacing in substrings is not equal to replacing in the full string. But that could of course be worked around. This is just a hint as to what you will have to do to get it working.
Peter Lindqvist