str_replace заменяет только определенное событие?

У меня есть эта команда SQL:

$sql = "INSERT INTO foo (value, value2, value3) 
        VALUES (value1, value2, value3)";

И я хочу заменить первый ) на , custom_value), Аналогично второй ) на , 1234567890)

Результат должен быть таким:

$sql = "INSERT INTO foo (value, value2, value3, custom_value) 
        VALUES (value1, value2, value3, 1234567890)";

Я попытался заменить все вхождения, используя str_replace().

Есть ли что-то с возможностью замены только определенного вхождения?


person JackWill    schedule 28.03.2012    source источник


Ответы (5)


Попробуйте следующее:

$sql = str_replace('value3', 'value3, %s', $sql);
$sql = sprintf($sql, 'custom_value', '1234567890');

Протестируйте мою локальную установку:

$sql = '(value, value2, value3) (value1, value2, value3)';
$sql = str_replace('value3', 'value3, %s', $sql);
$sql = sprintf($sql, 'custom_value', '1234567890');

// produces (value, value2, value3, custom_value) (value1, value2, value3, 1234567890)
echo $sql; 

Вот повторно используемая функция:

function replace_occurence($search, $replace, $subject) {
        $subject = str_replace($search, '%s', $subject);
        array_unshift($replace, $subject);
        return call_user_func_array('sprintf', $replace);
}
$sql = '(value, value2, value3) (value1, value2, value3)';
$sql = replace_occurence(')', array(', custom_value)', ', 123456790)'), $sql);
person Andreas Wong    schedule 28.03.2012
comment
@Kaii полностью пропустил вопрос: S, скоро удалю это. Спасибо - person Andreas Wong; 28.03.2012
comment
@Kaii Я тестировал локально, и он работает, производя (value, value2, value3, custom_value) (value1, value2, value3, 1234567890), поэтому не совсем уверен, что вы подразумеваете под sprintf(), он молча выйдет из строя, вы тестировали мой код или я что-то здесь упустил? - person Andreas Wong; 28.03.2012
comment
@andreas хорошо, ты прав в этом вопросе, я ответил слишком быстро. Но то, что я изначально сказал, по-прежнему верно: это всего лишь пример, и очень маловероятно, что value3 является значением для поля value3 в производственном коде. ОП запросил замену круглой скобки, и это действительно то, что вы должны сделать. Код, который работает только на конкретном примере, вообще бесполезен. - person Kaii; 28.03.2012

Для примера, который вы привели... вы можете использовать это регулярное выражение:

#(\).+?\(.+)(\))#

В PHP-коде это выглядит так:

$sql = preg_replace("#(\).+?\(.+)(\))#", 
                    ", custom_value\1, 1234567890\2", 
                    $sql, -1, $count);

он будет искать закрытую скобку, за которой следует открытая скобка, и после этого будет искать последнюю закрытую скобку

Пример: http://xrg.es/#b1uu3f

person SERPRO    schedule 28.03.2012
comment
работает только в конкретном примере. Фактический код SQL будет выглядеть так: INSERT INTO foo (value, value2, value3) VALUES (value1, value2, value3), который регулярное выражение не сможет правильно заменить. - person Kaii; 28.03.2012
comment
Простое исправление проблемы, которую вы предложили... теперь код должен работать - person SERPRO; 28.03.2012

В базовом наборе функций PHP такого нет. Но вы можете реализовать это с помощью substr_replace().

$sql = "foo (bar, baz, blub) bar (boo, far, faz)";

// only replace first occurance
$firstpos = strpos($sql, ')');
$sql = substr_replace($sql, ', custom_value)', $firstpos, 1);

// only replace second occurance
$secondpos = strpos( $sql, ')', strpos( $sql, ')' ) + 1);
$sql = substr_replace( $sql, ', 123456)', $secondpos, 1);

echo $sql, PHP_EOL;

Полученные результаты:

foo (bar, baz, blub, custom_value) bar (boo, far, faz, 123456)

Переписано как повторно используемая функция:

function str_replace_occurance($search, $replace, $subject, $occurance) {
   $pos = NULL;
   for ($i = 1; $i <= $occurance; $i++) {
       $pos = strpos($subject, $search, ($pos===NULL) ? 0 : $pos+1);
   }
   return substr_replace($subject, $replace, $pos, strlen($search));
}

$sql = str_replace_occurance(')', ', custom_value)', $sql, 1);
$sql = str_replace_occurance(')', ', 1234567890)', $sql, 2);
echo $sql, PHP_EOL;

Редактировать: изменен порядок параметров, чтобы они имели тот же порядок и имя, что и исходные str_replace

person Kaii    schedule 28.03.2012

Если у вас php> 5.0, вы можете использовать count в str_replace, чтобы указать, сколько замен вам нужно.

person slash197    schedule 28.03.2012
comment
параметр count на самом деле является ссылкой на переменную, где str_replace() возвращает количество замененных вхождений. Это не параметр ограничения или смещения. - person Kaii; 29.03.2012

Если вы используете только str_replace, тогда str_replace с ограничением для 1-го и снова замените его на второй...

http://au.php.net/manual/en/function.str-replace.php

person KoolKabin    schedule 28.03.2012
comment
для str_replace() нет параметра ограничения. Кроме того, если бы он был, второй вызов все равно заменил бы первый вызов. - person Kaii; 29.03.2012