Как заменить несколько подстрок в строке?

Есть строка
text :pattern1 text :pattern2 text :pattern3
Есть два массива
$array1=array('/:pattern1/', '/:pattern2/', '/:pattern3/');
$array2=array(':pattern2', ':pattern3', 'foo');

Нужно по порядку заменить элементы первого массива на второй, т.б. должна получиться строка
text :pattern2 text :pattern3 text foo

Пробовал вариант
$str='text :pattern1 text :pattern2 text :pattern3';
$array1=array('/:pattern1/', '/:pattern2/', '/:pattern3/');
$array2=array(':pattern2', ':pattern3', 'foo');
echo preg_replace($array1, $array2, $str, 1);

Результат таков
text foo text :pattern2 text :pattern3
Т.е. функция производит замену последовательно в три этапа
:pattern1 => :pattern2 = 'text :pattern2 text :pattern2 text :pattern3'
:pattern2 => :pattern3 = 'text :pattern3 text :pattern2 text :pattern3'
:pattern3 => foo = 'text foo text :pattern2 text :pattern3'


Могу, конечно, организовать замены значений на рандомные хеши, используя вспомогательные массивы и циклы, но хотелось бы посмотреть на ваши варианты
  • Вопрос задан
  • 3306 просмотров
Решения вопроса 1
ViktorBurakov
@ViktorBurakov Автор вопроса
В общем придётся использовать это, решение не плохое, но не очень быстрое
/**
 * @param string $string
 * @param (assoc)array $arguments
 * @return string
 */
function argumentsReplace($string, $arguments) {
	$arr=array();
	foreach($arguments as $k => $v) {
		$hash=md5($k).rand(20000,999999);
		$arr[$hash]=$v;
		$string=str_replace($k, $hash, $string);
		}
	return str_replace(array_keys($arr), array_values($arr), $string);
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 4
papahoolio
@papahoolio
Вот конкретно для твоего примера

$str='text :pattern1 text :pattern2 text :pattern3';
$array1=array_reverse(array('/:pattern1/', '/:pattern2/', '/:pattern3/'));
$array2= array_reverse(array(':pattern2', ':pattern3', 'foo'));
echo preg_replace($array1, $array2, $str);


а что у тебя там в реальной задаче может быть из твоего описания я так и не понял
Ответ написан
fornit1917
@fornit1917
Боюсь сходу ошибиться, но по-моему формально условие будет таким: чтобы замена корректно сработала массивы должны быть упорядочены таким образом, что для всех i>=0 и i < N-1 (N - количество замен) и для всех j > i и j <= N-1 выполнялось условие: array2[$j] не содержится среди элементов $array1[0], ..., $array1[$i].
Ответ написан
fornit1917
@fornit1917
Так бы сразу и спросили: как в PDO подстановка значений в параметризованный запрос происходит.
А происходит она совсем не через str_replace. Происходит она через парсинг запроса на отдельные компоненты. Выстраивается специальная структура данных (не строка!). Когда вы вызываете bindValue или bindParam подстановка значений происходит в эту самую разобранную структуру данных, которая собирается обратно в строковый SQL-запрос только перед выполнением.
Если интересно, то вот один из исходников, где это все реализовано: https://github.com/php/php-src/blob/dd7c33d0c9812df09a029d32451decb012d42629/ext/mysqlnd/mysqlnd_ps.c
Ответ написан
ruFelix
@ruFelix
Предсказание будущего по руке, таро, кофе.
То, что элементы первого массива фиксированы, а элементы второго массива задаются пользователем.
SQL в PDO записывается так: SELECT * FROM table `name`=:name AND pass=:pass
Далее мы даём на обработку массив array(':name'=>$name,':pass'=>$pass)
В PDO отлично заменяет.


$name = 'test';
$pass = 'name:qwe';
$query = 'SELECT * FROM table `name`=:name AND pass=:pass';
$arg = array(':name'=>$name,':pass'=>$pass);

$query = str_replace(array_keys($arg),array_values($arg),$query);

var_dump($query);


Вам это было нужно?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы