preg_replace - массив отдельных замен - PullRequest
2 голосов
/ 01 декабря 2009

Я пытаюсь добиться следующего:

$subject = 'a b a';<br> $search = 'a';<br> $replace = '1';

Желаемый результат:

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

Есть ли способ добиться этого с помощью preg_replace?

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

вернет все замены в одном и том же результате:

Array<br> (<br> [0] => 1 b 1<br> )

Приветствия

Ответы [ 2 ]

1 голос
/ 01 декабря 2009
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'));

выход

Array
(
    [0] => 1 b a
    [1] => a b 1
)
1 голос
/ 01 декабря 2009

Я думаю, что это невозможно. Вы можете указать предел замен в необязательном четвертом параметре, но он всегда начинается с начала.

Можно достичь того, что вы ищете, с помощью preg_split(). Вам просто нужно будет разбить вашу строку во всех случаях вашего шаблона поиска, а затем связываться с ними по одному. Если ваш шаблон поиска - просто строка, вы можете добиться того же с помощью explode(). Если вам понадобится помощь в разработке этого подхода, я буду рад помочь.

РЕДАКТИРОВАТЬ : Давайте посмотрим, работает ли это для вас:

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

Примечание: это еще не проверено. Пожалуйста, сообщите, работает ли он.

РЕДАКТИРОВАТЬ 2 :

Я протестировал его на вашем примере сейчас, исправил несколько вещей, и теперь он работает (по крайней мере, с этим примером).

...