Intereting Posts
Распределить значение массива в столбце таблицы PHP создает случайный файл tmp и получает полный путь Удалить значение из строки запроса. Часть 2 Вложенный, если он не работает в php, ничего не делает или идет в конец кода Как установить файлы cookie в течение 20 минут и проверить, истек ли срок их действия Получить токен безопасности для незарегистрированного пользователя с помощью Symfony Как выполнять команды оболочки синхронно в PHP Динамический вызов функции PHP создание массива ассоциативного массива в jquery Как вставить значения из датпикера JQuery в формат даты в MySQL с помощью Codeigniter? Посещение базы данных – вставка нескольких записей в один запрос Когда я должен объявлять переменные в классе PHP? База данных SQLite, размещенная на Heroku, автоматически сбрасывается Вставка вложенного массива JSON в качестве параметра в базе данных php mysql Как я могу найти, какой домен запрашивает iframe с моего сервера и сохраняет домен в базе данных

Использование str_replace так, чтобы оно действовало только в первом матче?

Я хочу версию str_replace() которая заменяет первое вхождение $search в $subject . Есть ли простое решение для этого, или мне нужно хакерское решение?

Related of "Использование str_replace так, чтобы оно действовало только в первом матче?"

Может быть сделано с preg_replace :

 function str_replace_first($from, $to, $subject) { $from = '/'.preg_quote($from, '/').'/'; return preg_replace($from, $to, $subject, 1); } echo str_replace_first('abc', '123', 'abcdef abcdef abcdef'); // outputs '123def abcdef abcdef' 

Магия находится в необязательном четвертом параметре [Предел]. Из документации:

[Предел] – Максимально возможные замены для каждого шаблона в каждой строке темы. По умолчанию -1 (без ограничений).

Хотя, см . Ответ зомбата для более эффективного метода (примерно, в 3-4 раза быстрее).

Там нет версии, но решение совсем не хаки.

 $pos = strpos($haystack, $needle); if ($pos !== false) { $newstring = substr_replace($haystack, $replace, $pos, strlen($needle)); } 

Довольно легко, и сохраняет штраф за выполнение регулярных выражений.

Бонус: если вы хотите заменить последнее вхождение, просто используйте strrpos вместо strpos .

Изменить: оба ответа были обновлены и теперь правильны. Я оставлю ответ, поскольку тайминги функции по-прежнему полезны.

Ответы «zombat» и «too much php», к сожалению, неверны. Это пересмотр ответа на сообщение zombat (поскольку у меня недостаточно репутации, чтобы опубликовать комментарий):

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

Это пересмотренный ответ «too much php»:

 implode($replace, explode($search, $subject, 2)); 

Обратите внимание на 2 в конце, а не на 1. Или в формате функции:

 function str_replace_first($search, $replace, $subject) { return implode($replace, explode($search, $subject, 2)); } 

Я приурочил две функции, а первая – в два раза быстрее, когда совпадение не найдено. Они совпадают с совпадением.

Я задавался вопросом, какой из них был самым быстрым, поэтому я проверил их все.

Ниже вы найдете:

  • Полный список всех функций, которые были внесены на эту страницу
  • Тестирование теста для каждой задачи (среднее время выполнения более 10 000 прогонов)
  • Ссылки на каждый ответ (для полного кода)

Все функции были протестированы с одинаковыми настройками:

 $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.BS [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.BS [AVERAGE TIME] => 0.0000084460 [SLOWER BY] => 24.05% 

К сожалению, я не знаю никакой функции 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)); } 

Я создал эту небольшую функцию, которая заменяет строку на строку (с учетом регистра) с лимитом, без необходимости в 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 

Самый простой способ – использовать регулярное выражение.

Другой способ – найти позицию строки с strpos (), а затем substr_replace ()

Но я бы действительно пошел на RegExp.

 $string = 'this is my world, not my world'; $find = 'world'; $replace = 'farm'; $result = preg_replace("/$find/",$replace,$string,1); echo $result; 
 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», например:

 $a='I love you'; echo str_replace_first('o','ea',$a); //output: I leave you 

Функция:

 function str_replace_first($this,$that,$where) { $b=strpos($where,$this); return substr($where,0,$b).$that.substr($where,$b+1); } , function str_replace_first($this,$that,$where) { $b=strpos($where,$this); return substr($where,0,$b).$that.substr($where,$b+1); } 

Чтобы расширить ответ на @ renocor , я написал функцию, которая на 100% обратно совместима с str_replace() . То есть вы можете заменить все вхождения str_replace() на str_replace_limit() без каких-либо 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 (eg '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 (eg 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; } } при <?php /** * Checks if $string is a valid integer. Integers provided as strings (eg '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 (eg 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; } } при <?php /** * Checks if $string is a valid integer. Integers provided as strings (eg '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 (eg 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; } } 

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

Фрагмент, который воспроизводит только первую букву строки:

 $word[0] = str_replace($find, $replace, $word[0]); 

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

 $word{0} = str_replace( array('ą', 'ż', 'ś', 'ź', 'ę', 'ć', 'ł', 'ó', 'ń'), array('Ą', 'Ż', 'Ś', 'Ź', 'Ę', 'Ć', 'Ł', 'Ó', 'Ń'), $word{0} ); 

Согласно моему результату тестирования, я хотел бы проголосовать за обычный_express, предоставленный 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 не так уж плоха, как думают многие. Поэтому я предлагаю классное решение, если ваш обычный экспресс не является сложным.

Чтобы расширить ответ на зомбат (который я считаю лучшим ответом), я создал рекурсивную версию его функции, которая принимает параметр $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; } } } 

Для строки

 $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.BS //replace ONLY LAST occurance of "OOOO" with "B" $string = strrev(implode(strrev($replace),explode(strrev($search),strrev($string),2))) //$string => OOO.OOO.BS 

Для одного символа

 $string[strpos($string,$search)] = $replace; //EXAMPLE $string = 'OOOOS'; $search = 'O'; $replace = 'B'; //replace ONLY FIRST occurance of "O" with "B" $string[strpos($string,$search)] = $replace; //$string => BOOOS //replace ONLY LAST occurance of "O" with "B" $string[strrpos($string,$search)] = $replace; // $string => BOOBS 

В дополнение к тому, что говорили люди, помните, что вся строка – это массив:

 $string = "Lorem ipsum lá lá lá"; $string[0] = "B"; echo $string; 

«Borem ipsum lá lá lá»

Вы можете использовать это:

 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 

Это может немного снизить производительность, но это самое простое решение.

Эта функция сильно вдохновлена ​​ответом @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; } 

Вот простой класс, который я создал, чтобы обернуть наши слегка измененные функции 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 eg 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 eg 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 ($ find, $ replace, $ subject, -3) должно заменить последние три экземпляра.

В любом случае просто предложение.

это мой первый ответ здесь, я надеюсь сделать это правильно. Почему бы не использовать четвертый аргумент функции str_replace для этой проблемы?

 mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] ) 

count: Если это будет принято, будет установлено количество выполненных замен.

edit: Этот ответ неверен, поскольку 4-й параметр str_replace – это переменная, которой назначается количество выполненных замен. Это несовместимо с preg_replace , который имеет 4-й параметр $limit и 5-й параметр &$count .