Я хочу версию, str_replace()
которая заменяет только первое вхождение $search
в $subject
. Есть ли простое решение для этого, или мне нужно хакерское решение?
Я хочу версию, str_replace()
которая заменяет только первое вхождение $search
в $subject
. Есть ли простое решение для этого, или мне нужно хакерское решение?
Ответы:
Может быть сделано с помощью preg_replace :
function str_replace_first($from, $to, $content)
{
$from = '/'.preg_quote($from, '/').'/';
return preg_replace($from, $to, $content, 1);
}
echo str_replace_first('abc', '123', 'abcdef abcdef abcdef');
// outputs '123def abcdef abcdef'
Магия заключается в необязательном четвертом параметре [Limit]. Из документации:
[Limit] - максимально возможное количество замен для каждого шаблона в каждой строке темы. По умолчанию -1 (без ограничений).
Тем не менее, смотрите ответ зомбата для более эффективного метода (примерно, в 3-4 раза быстрее).
preg_quote
? Например, @ThomasRedstone беспокоится о том, что разделитель /
может быть опасным, если он появляется $from
, но, к счастью, это не так: он корректно экранируется из-за preg_quote
второго параметра (это легко проверить). Мне было бы интересно услышать о конкретных проблемах (которые будут серьезными ошибками безопасности PCRE в моей книге).
Нет никакой версии, но решение совсем не хакерское.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Довольно просто и экономит потери производительности регулярных выражений.
Бонус: если вы хотите заменить последнее вхождение, просто используйте strrpos
вместо strpos
.
substr_replace
это довольно громоздкая функция для использования из-за всех параметров, реальная проблема заключается в том, что иногда манипулирование строками с помощью чисел просто сложно - нужно быть осторожным, чтобы передать правильную переменную / смещение в функции. На самом деле я бы сказал, что приведенный выше код является наиболее простым и логичным подходом.
Изменить: оба ответа были обновлены и теперь верны. Я оставлю ответ, так как функции времени все еще полезны.
Ответы «зомбат» и «слишком много PHP», к сожалению, не верны. Это ревизия к опубликованному зомбату ответа (так как у меня недостаточно репутации, чтобы оставлять комментарии):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Обратите внимание на strlen ($ needle) вместо strlen ($ replace). Пример Zombat будет работать правильно только если иглы и замены имеют одинаковую длину.
Вот та же функциональность в функции с той же сигнатурой, что и в собственном str_replace в PHP:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
Это пересмотренный ответ «слишком много PHP»:
implode($replace, explode($search, $subject, 2));
Обратите внимание на 2 в конце вместо 1. Или в формате функции:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Я синхронизировал две функции, и первая из них работает в два раза быстрее, когда совпадений не найдено. Они одинаковой скорости, когда совпадение найдено.
stripos()
на помощь :-)
Я задавался вопросом, какой из них был самым быстрым, поэтому я проверил их все.
Ниже вы найдете:
Все функции были протестированы с одинаковыми настройками:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Функции, которые заменяют только первое вхождение строки в строке:
substr_replace($string, $replace, 0, strlen($search));
[CONTRIBUTED BY] => zombat
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000062883
[SLOWER BY] => FASTEST
replace_first($search, $replace, $string);
[CONTRIBUTED BY] => too much php
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000073902
[SLOWER BY] => 17.52%
preg_replace($search, $replace, $string, 1);
[CONTRIBUTED BY] => karim79
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000077519
[SLOWER BY] => 23.27%
str_replace_once($search, $replace, $string);
[CONTRIBUTED BY] => happyhardik
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000082286
[SLOWER BY] => 30.86%
str_replace_limit($search, $replace, $string, $count, 1);
[CONTRIBUTED BY] => bfrohs - expanded renocor
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000083342
[SLOWER BY] => 32.54%
str_replace_limit($search, $replace, $string, 1);
[CONTRIBUTED BY] => renocor
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000093116
[SLOWER BY] => 48.08%
str_replace_limit($string, $search, $replace, 1, 0);
[CONTRIBUTED BY] => jayoaK
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000093862
[SLOWER BY] => 49.26%
Функции, которые заменяют только последнее вхождение строки в строке:
substr_replace($string, $replace, strrpos($string, $search), strlen($search));
[CONTRIBUTED BY] => oLinkSoftware - modified zombat
[OOO.OOO.OOO.S] => OOO.OOO.B.S
[AVERAGE TIME] => 0.0000068083
[SLOWER BY] => FASTEST
strrev(implode(strrev($replace), explode(strrev($search), strrev($string), 2)));
[CONTRIBUTED BY] => oLinkSoftware
[OOO.OOO.OOO.S] => OOO.OOO.B.S
[AVERAGE TIME] => 0.0000084460
[SLOWER BY] => 24.05%
substr_replace()
выигрывает результат, проста; потому что это внутренняя функция. Две внутренние и пользовательские функции, выполняющие одно и то же, отличаются по производительности, поскольку внутренняя функция работает на более низких уровнях. Так почему бы и нет preg_match()
? Регулярные выражения почти медленнее, чем любая внутренняя функция манипуляции со строками, из-за того, что они ищут несколько раз в строке.
substr_replace($string, $replace, 0, strlen($search));
) не просто записал эту статическую 0
. Частью свертки решений без регулярных выражений является то, что им нужно «найти» отправную точку, прежде чем знать, где заменить.
К сожалению, я не знаю ни одной функции PHP, которая может это сделать.
Вы можете свернуть свой собственный довольно легко, как это:
function replace_first($find, $replace, $subject) {
// stolen from the comments at PHP.net/str_replace
// Splits $subject into an array of 2 items by $find,
// and then joins the array with $replace
return implode($replace, explode($find, $subject, 2));
}
return implode($replace, explode($find, $subject, $limit+1));
для пользовательских замен номера
Я создал эту маленькую функцию, которая заменяет строку на строку (с учетом регистра) с помощью limit, без необходимости использования Regexp. Работает нормально.
function str_replace_limit($search, $replace, $string, $limit = 1) {
$pos = strpos($string, $search);
if ($pos === false) {
return $string;
}
$searchLen = strlen($search);
for ($i = 0; $i < $limit; $i++) {
$string = substr_replace($string, $replace, $pos, $searchLen);
$pos = strpos($string, $search);
if ($pos === false) {
break;
}
}
return $string;
}
Пример использования:
$search = 'foo';
$replace = 'bar';
$string = 'foo wizard makes foo brew for evil foo and jack';
$limit = 2;
$replaced = str_replace_limit($search, $replace, $string, $limit);
echo $replaced;
// bar wizard makes bar brew for evil foo and jack
===false
вместо того , is_bool(
чтобы быть более четко - я даю этот палец вверх только потому , что он избежал RegExp безумие ! ... и в то же время это рабочее и чистое решение ...
preg_
решение - это не безумие, а личное предпочтение. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
довольно просто читать для людей, которые не боятся регулярных выражений. Нужен поиск без учета регистра? Добавьте i
после конца шаблон разделителя. Нужна поддержка Unicode / Multibyte? Добавьте u
после конца шаблон разделителя. Нужна поддержка границ слов? Добавьте \b
по обе стороны вашей строки поиска. Если вы не хотите регулярное выражение, не используйте регулярное выражение. Лошади на курсах, но уж точно не безумие.
Самый простой способ - использовать регулярные выражения.
Другой способ - найти позицию строки с помощью strpos (), а затем substr_replace ().
Но я бы действительно пошел на RegExp.
function str_replace_once($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos === false) {
return $subject;
}
return substr($subject, 0, $pos) . $replace . substr($subject, $pos + strlen($search));
}
=> КОД БЫЛ ПЕРЕСМОТРЕН, поэтому считаю некоторые комментарии слишком старыми
И спасибо всем за помощь в улучшении этого
Любая ошибка, пожалуйста, сообщите мне; Я исправлю это сразу после
Итак, давайте перейдем к:
Замена первого 'o' на 'ea', например:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
Функция:
function str_replace_first($a,$b,$s)
{
$w=strpos($s,$a);
if($w===false)return $s;
return substr($s,0,$w).$b.substr($s,$w+strlen($a));
}
substr($where,$b+strlen($this))
, а не substr($where,$b+1)
. И я думаю, что substr_replace
это быстрее.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
из , $find
прежде чем использовать его в качестве выражения.
preg_quote()
. Этот поздний дубликат ответа можно безопасно удалить со страницы, поскольку его рекомендации предоставлены более ранним и более высоко оцененным принятым ответом.
Чтобы расширить ответ @ renocor , я написал функцию, которая на 100% обратно совместима с str_replace()
. То есть, вы можете заменить все вхождения str_replace()
с str_replace_limit()
не портя ничего, даже те , используя массивы для $search
, $replace
и / или $subject
.
Функция могла бы быть полностью автономной, если бы вы хотели заменить вызов функции на ($string===strval(intval(strval($string))))
, но я бы порекомендовал против нее, так valid_integer()
как это довольно полезная функция, когда речь идет о целых числах, представленных в виде строк.
Примечание. По возможности str_replace_limit()
будет использоваться str_replace()
вместо этого, чтобы str_replace()
можно было заменить все вызовы, str_replace_limit()
не беспокоясь о снижении производительности.
<?php
$search = 'a';
$replace = 'b';
$subject = 'abcabc';
$limit = -1; // No limit
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 замены - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 замена - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 замены - bbcbbc
<?php
/**
* Checks if $string is a valid integer. Integers provided as strings (e.g. '2' vs 2)
* are also supported.
* @param mixed $string
* @return bool Returns boolean TRUE if string is a valid integer, or FALSE if it is not
*/
function valid_integer($string){
// 1. Cast as string (in case integer is provided)
// 1. Convert the string to an integer and back to a string
// 2. Check if identical (note: 'identical', NOT just 'equal')
// Note: TRUE, FALSE, and NULL $string values all return FALSE
$string = strval($string);
return ($string===strval(intval($string)));
}
/**
* Replace $limit occurences of the search string with the replacement string
* @param mixed $search The value being searched for, otherwise known as the needle. An
* array may be used to designate multiple needles.
* @param mixed $replace The replacement value that replaces found search values. An
* array may be used to designate multiple replacements.
* @param mixed $subject The string or array being searched and replaced on, otherwise
* known as the haystack. If subject is an array, then the search and replace is
* performed with every entry of subject, and the return value is an array as well.
* @param string $count If passed, this will be set to the number of replacements
* performed.
* @param int $limit The maximum possible replacements for each pattern in each subject
* string. Defaults to -1 (no limit).
* @return string This function returns a string with the replaced values.
*/
function str_replace_limit(
$search,
$replace,
$subject,
&$count,
$limit = -1
){
// Set some defaults
$count = 0;
// Invalid $limit provided. Throw a warning.
if(!valid_integer($limit)){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting an '.
'integer', E_USER_WARNING);
return $subject;
}
// Invalid $limit provided. Throw a warning.
if($limit<-1){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting -1 or '.
'a positive integer', E_USER_WARNING);
return $subject;
}
// No replacements necessary. Throw a notice as this was most likely not the intended
// use. And, if it was (e.g. part of a loop, setting $limit dynamically), it can be
// worked around by simply checking to see if $limit===0, and if it does, skip the
// function call (and set $count to 0, if applicable).
if($limit===0){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting -1 or '.
'a positive integer', E_USER_NOTICE);
return $subject;
}
// Use str_replace() whenever possible (for performance reasons)
if($limit===-1){
return str_replace($search, $replace, $subject, $count);
}
if(is_array($subject)){
// Loop through $subject values and call this function for each one.
foreach($subject as $key => $this_subject){
// Skip values that are arrays (to match str_replace()).
if(!is_array($this_subject)){
// Call this function again for
$this_function = __FUNCTION__;
$subject[$key] = $this_function(
$search,
$replace,
$this_subject,
$this_count,
$limit
);
// Adjust $count
$count += $this_count;
// Adjust $limit, if not -1
if($limit!=-1){
$limit -= $this_count;
}
// Reached $limit, return $subject
if($limit===0){
return $subject;
}
}
}
return $subject;
} elseif(is_array($search)){
// Only treat $replace as an array if $search is also an array (to match str_replace())
// Clear keys of $search (to match str_replace()).
$search = array_values($search);
// Clear keys of $replace, if applicable (to match str_replace()).
if(is_array($replace)){
$replace = array_values($replace);
}
// Loop through $search array.
foreach($search as $key => $this_search){
// Don't support multi-dimensional arrays (to match str_replace()).
$this_search = strval($this_search);
// If $replace is an array, use the value of $replace[$key] as the replacement. If
// $replace[$key] doesn't exist, just an empty string (to match str_replace()).
if(is_array($replace)){
if(array_key_exists($key, $replace)){
$this_replace = strval($replace[$key]);
} else {
$this_replace = '';
}
} else {
$this_replace = strval($replace);
}
// Call this function again for
$this_function = __FUNCTION__;
$subject = $this_function(
$this_search,
$this_replace,
$subject,
$this_count,
$limit
);
// Adjust $count
$count += $this_count;
// Adjust $limit, if not -1
if($limit!=-1){
$limit -= $this_count;
}
// Reached $limit, return $subject
if($limit===0){
return $subject;
}
}
return $subject;
} else {
$search = strval($search);
$replace = strval($replace);
// Get position of first $search
$pos = strpos($subject, $search);
// Return $subject if $search cannot be found
if($pos===false){
return $subject;
}
// Get length of $search, to make proper replacement later on
$search_len = strlen($search);
// Loop until $search can no longer be found, or $limit is reached
for($i=0;(($i<$limit)||($limit===-1));$i++){
// Replace
$subject = substr_replace($subject, $replace, $pos, $search_len);
// Increase $count
$count++;
// Get location of next $search
$pos = strpos($subject, $search);
// Break out of loop if $needle
if($pos===false){
break;
}
}
// Return new $subject
return $subject;
}
}
E_USER_WARNING
во всем , что является предупреждением , не ошибка . Обратная трассировка чрезвычайно полезна, чтобы выяснить, какой код передает некорректные данные функции в первую очередь (что абсолютно необходимо для отслеживания ошибок в работе). Что касается возврата $subject
вместо false
/ null
или выдачи ошибки, это был просто личный выбор для моего варианта использования. Чтобы соответствовать str_replace()
функциональным возможностям, лучше всего использовать подхватываемые фатальные ошибки (как str_replace()
при закрытии первых двух аргументов).
preg_replace()
. Кроме того, preg_replace()
/ regex предлагает обработку границ слов (если желательно) - то, что не-регулярные функции не будут предоставлять элегантно.
Согласно результатам моего теста, я бы хотел проголосовать за обычный_экспресс, предоставленный karim79. (У меня недостаточно репутации, чтобы проголосовать сейчас!)
Решение от zombat использует слишком много вызовов функций, я даже упрощаю коды. Я использую PHP 5.4 для запуска обоих решений 100 000 раз, и вот результат:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1,85 сек
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1,35 сек
Как вы видете. Производительность preg_replace не так плоха, как думают многие. Поэтому я бы предложил классное решение, если ваш регулярный экспресс не сложен.
$pos
на false
, так что, когда игла не существует в стоге сена, это повредит выход.
Чтобы расширить ответ зомбата (который я считаю лучшим), я создал рекурсивную версию его функции, которая принимает $limit
параметр, чтобы указать, сколько вхождений вы хотите заменить.
function str_replace_limit($haystack, $needle, $replace, $limit, $start_pos = 0) {
if ($limit <= 0) {
return $haystack;
} else {
$pos = strpos($haystack,$needle,$start_pos);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
return str_replace_limit($newstring, $needle, $replace, $limit-1, $pos+strlen($replace));
} else {
return $haystack;
}
}
}
$start_pos
, поэтому , если он находится за пределами длины строки, то эта функция будет генерировать: Warning: strpos(): Offset not contained in string...
. Эта функция не может произвести замену, если она $start_pos
находится за пределами длины. Доказательство отказа: 3v4l.org/qGuVIR ... Ваша функция может объединять return $haystack
условия и избегать объявления одноразовых переменных, например: 3v4l.org/Kdmqp. Однако, как я уже говорил в комментариях в других местах на этой странице, я бы предпочел используйте очень чистый, прямой, нерекурсивный preg_replace()
вызов.
else
Постулаты$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Для строки
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
//replace ONLY FIRST occurance of "OOO" with "B"
$string = substr_replace($string,$replace,0,strlen($search));
//$string => B.OOO.OOO.S
//replace ONLY LAST occurance of "OOOO" with "B"
$string = substr_replace($string,$replace,strrpos($string,$search),strlen($search))
//$string => OOO.OOO.B.S
//replace ONLY LAST occurance of "OOOO" with "B"
$string = strrev(implode(strrev($replace),explode(strrev($search),strrev($string),2)))
//$string => OOO.OOO.B.S
Для одного персонажа
$string[strpos($string,$search)] = $replace;
//EXAMPLE
$string = 'O.O.O.O.S';
$search = 'O';
$replace = 'B';
//replace ONLY FIRST occurance of "O" with "B"
$string[strpos($string,$search)] = $replace;
//$string => B.O.O.O.S
//replace ONLY LAST occurance of "O" with "B"
$string[strrpos($string,$search)] = $replace;
// $string => B.O.O.B.S
substr_replace()
метода повреждают входную строку, когда поисковое значение отсутствует. Доказательство неудачи: 3v4l.org/HmEml (И эта последняя техника со всеми rev
вызовами серьезно запутана /
В дополнение к тому, что говорили люди, помните, что вся строка является массивом:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á
. Демонстрация неудачи
string
многобайтовая строка, используяmb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Используя substr_replace, мы можем заменить вхождение первого символа только в строке. как & повторяется несколько раз, но только на первой позиции, которую мы должны заменить & на?
Эта функция в значительной степени вдохновлена ответом @renocor. Это делает функцию многобайтовой безопасной.
function str_replace_limit($search, $replace, $string, $limit)
{
$i = 0;
$searchLength = mb_strlen($search);
while(($pos = mb_strpos($string, $search)) !== false && $i < $limit)
{
$string = mb_substr_replace($string, $replace, $pos, $searchLength);
$i += 1;
}
return $string;
}
function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = null)
{
$string = (array)$string;
$encoding = is_null($encoding) ? mb_internal_encoding() : $encoding;
$length = is_null($length) ? mb_strlen($string) - $start : $length;
$string = array_map(function($str) use ($replacement, $start, $length, $encoding){
$begin = mb_substr($str, 0, $start, $encoding);
$end = mb_substr($str, ($start + $length), mb_strlen($str), $encoding);
return $begin . $replacement . $end;
}, $string);
return ( count($string) === 1 ) ? $string[0] : $string;
}
Вы можете использовать это:
function str_replace_once($str_pattern, $str_replacement, $string){
if (strpos($string, $str_pattern) !== false){
$occurrence = strpos($string, $str_pattern);
return substr_replace($string, $str_replacement, strpos($string, $str_pattern), strlen($str_pattern));
}
return $string;
}
Нашел этот пример с php.net
Использование:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Вывод:
ThiZ iz an examplz
Это может немного снизить производительность, но самое простое решение.
strpos()
). Понижено, потому что это не добавляет никакого нового значения к странице.
Если ваша строка не содержит многобайтовых символов и если вы хотите заменить только один символ, вы можете просто использовать strpos
Здесь функция, которая обрабатывает ошибки
/**
* Replace the first occurence of given string
*
* @param string $search a char to search in `$subject`
* @param string $replace a char to replace in `$subject`
* @param string $subject
* @return string
*
* @throws InvalidArgumentException if `$search` or `$replace` are invalid or if `$subject` is a multibytes string
*/
function str_replace_first(string $search , string $replace , string $subject) : string {
// check params
if(strlen($replace) != 1 || strlen($search) != 1) {
throw new InvalidArgumentException('$search & $replace must be char');
}elseif(mb_strlen($subject) != strlen($subject)){
throw new InvalidArgumentException('$subject is an multibytes string');
}
// search
$pos = strpos($subject, $search);
if($pos === false) {
// not found
return $subject;
}
// replace
$subject[$replace] = $subject;
return $subject;
}
Для петлевого решения
<?php
echo replaceFirstMatchedChar("&", "?", "/property/details&id=202&test=123#tab-6");
function replaceFirstMatchedChar($searchChar, $replaceChar, $str)
{
for ($i = 0; $i < strlen($str); $i++) {
if ($str[$i] == $searchChar) {
$str[$i] = $replaceChar;
break;
}
}
return $str;
}
Вот простой класс, который я создал, чтобы обернуть наши слегка модифицированные функции str_replace () .
Наша функция php :: str_rreplace () также позволяет вам выполнять обратную ограниченную функцию str_replace (), которая может быть очень полезна при попытке заменить только последние X экземпляры строки.
Оба эти примера используют preg_replace () .
<?php
class php {
/**
* str_replace() from the end of a string that can also be limited e.g. replace only the last instance of '</div>' with ''
*
* @param string $find
* @param string $replace
* @param string $subject
* @param int $replacement_limit | -1 to replace all references
*
* @return string
*/
public static function str_replace($find, $replace, $subject, $replacement_limit = -1) {
$find_pattern = str_replace('/', '\/', $find);
return preg_replace('/' . $find_pattern . '/', $replace, $subject, $replacement_limit);
}
/**
* str_replace() from the end of a string that can also be limited e.g. replace only the last instance of '</div>' with ''
*
* @param string $find
* @param string $replace
* @param string $subject
* @param int $replacement_limit | -1 to replace all references
*
* @return string
*/
public static function str_rreplace($find, $replace, $subject, $replacement_limit = -1) {
return strrev( self::str_replace(strrev($find), strrev($replace), strrev($subject), $replacement_limit) );
}
}
$str = "Hello there folks!"
$str_ex = explode("there, $str, 2); //explodes $string just twice
//outputs: array ("Hello ", " folks")
$str_final = implode("", $str_ex); // glues above array together
// outputs: str("Hello folks")
Есть еще один дополнительный пробел, но это не имело значения, как это было для сценария backgound в моем случае.
это мой первый ответ здесь, я надеюсь сделать это правильно. Почему бы не использовать четвертый аргумент функции str_replace для этой проблемы?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
количество: если передано, это будет установлено на количество выполненных замен.
edit: этот ответ неверный, потому что 4-й параметр str_replace является переменной, которой присваивается количество выполненных замен. Это несовместимо с preg_replace , который имеет 4-й параметр $limit
и 5-й параметр &$count
.
Легко найти решение, которое заменит только первую или первую пару экземпляров (указав значение счетчика). Существует не так много решений для замены последней или последней пары экземпляров.
Возможно, что-то вроде str_replace ($ find, $ replace, $ subject, -3) должно заменить последние три экземпляра.
Во всяком случае, просто предложение.
s($subject)->replaceFirst($search)
иs($subject)->replaceFirstIgnoreCase($search)
помочь, как найти в этой автономной библиотеке .