Как заменить множество совпадений в одной строке на разные значения?..

Статус
В этой теме нельзя размещать новые ответы.

bugargen

Местный житель
Регистрация
24 Апр 2008
Сообщения
234
Реакции
20
Есть текст вида:
PHP:
Сунул {KEY} руку в {KEY}
Есть функция ran(), которая возвращает случайное значение.

Нужно, чтобы КАЖДЫЙ раз, когда будет найдено вхождение {KEY}, вызывалась функция ran() с заменой {KEY} на возвращаемое ею значение!

Это просто сделать, если в каждой строке всего по одному {KEY}, а вот если их несколько - моск сломал уже :be:
 
примерно так

PHP:
<?php
  $text = 'Сунул {KEY} руку в {KEY}';
  function _rand($input) {
    // здесь делаешь какую-нибудь рандомную выборку из своего массива, выражениями из которого собрался заменять возвращаешь это в конце ф-ии.
    return ;
  }
  $text = preg_replace_callback('/{KEY}/', '_rand', $text);
  echo $text;
?>
Еще примеры
 
Вот альтернативный способ, в теории работающий чуть быстрее.
PHP:
while(strpos($str, '{KEY}') !== FALSE) {
	$str = preg_replace('#{KEY}#', ran(), $str, 1);
}
 
в теории работающий чуть быстрее
А на практике работающий логически по другому и имеющий теоретический потенциал впадения в бесконечный цикл ))
Да и каким образом компиляция одной регулярки и единичный проход по строке будет работать медленнее многократного повторения тех же действий? :)
 
PHP:
$str = preg_replace('%{KEY}%ie', "ran()", $str);
 
mOnsieur
Хотел, сразу-слёту, было возразить, ибо пробовал я уже решить свою задачу с помощью callback, но потом, оценив эту функцию ещё разок - я, наконец, нашёл нужный мне путь.
Возразить хотел, т.к. мне необходимо в свою функцию ran() передавать некое строковое значение, в зависимости от найденного вхождения, а в callback никаких дополнительных значений не впихнёшь, только название самой функции. В общем, решил я присвоение нужной строки делать в самой функции ran(). В итоге - всё просто замечательно работает! :ay:
Большое спасибо!

antn
Тебя, я так понимаю, тоже нужно поблагодарить, ибо ваши мысли были схожи :)

Holy Diver
Твой пример, это первое, что приходит в голову. Так я, изначально, и кодил. Но, сцуко, preg_replace сначала находит все совпадения в строке, а потом уже заменяет их всех ОДНИМ и ТЕМ ЖЕ значением! Плюс к этому, функция, которая указана в качестве замены - вызывается сама собой! Т.е., как только доходит до строки вида preg_replace('/{KEY}/', ran(), $str), в независимости от того: обнаружено вхождение или нет, функция ran() всё-равно вызывается! Меня это хорошенько побесило :D Кстати, об этом я создам сейчас отдельную тему, ибо очень актуально..

tostrss
Модификатор e я уже пробовал использовать... В итоге - сплошные эрорры парсинга и фатал ерроры. Я х.з., как вообще с этим модификатором обращаться. Но ты уже второй мне это советуешь..
 
antn
В данном случае никаких зацикливаний нет и быть не может. Быстрее работает в том случае, если таких макросов несколько десятков или сотен, и большей части из них в тексте не присутствует - то есть мой вариант не выполняет регулярку в случае отсутствия в строке конструкции вида {KEY} и им подобных. Нет универсального решения, под каждую задачу оно своё. Сравнения производительности обычного варианта и callback я ещё не встречал, так что это остаётся вопросом.

bugargen
А я бы сначала почитал документацию на функцию:
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit] )
....В случае, если параметр limit указан, будет произведена замена limit вхождений шаблона; в случае, если limit опущен либо равняется -1, будут заменены все вхождения шаблона.
Мой пример какраз-таки не страдает заменой всех ОДНИМ и ТЕМ ЖЕ значением.
 
Если ф-я ran вернёт строку содержащую {KEY} (условием это не запрещается), то эта подстрока будет заменена следующим проходом цикла. Если {KEY} будет присутствовать в возращаемом значении всегда, цикл не остановится.
Насчёт скорости дискутировать не буду - в php это экономия на спичках :)
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху