Quiero una versión de str_replace()
que sólo sustituye a la primera aparición de $search
la $subject
. ¿Hay una solución fácil para esto o necesito una solución hacky?
Quiero una versión de str_replace()
que sólo sustituye a la primera aparición de $search
la $subject
. ¿Hay una solución fácil para esto o necesito una solución hacky?
Respuestas:
Se puede hacer con 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'
La magia está en el cuarto parámetro opcional [Límite]. De la documentación:
[Límite]: el máximo de reemplazos posibles para cada patrón en cada cadena de asunto. El valor predeterminado es -1 (sin límite).
Sin embargo, vea la respuesta de zombat para un método más eficiente (aproximadamente, 3-4 veces más rápido).
preg_quote
? Por ejemplo, a @ThomasRedstone le preocupa que el delimitador /
pueda ser peligroso si aparece $from
, pero afortunadamente no lo es: se escapó correctamente debido al preg_quote
segundo parámetro (uno puede probarlo fácilmente). Me interesaría saber sobre problemas específicos (que serían serios errores de seguridad PCRE en mi libro).
No hay una versión de este, pero la solución no es nada hacky.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Bastante fácil y ahorra la penalización de rendimiento de las expresiones regulares.
Bonificación: si desea reemplazar la última ocurrencia, simplemente use strrpos
en lugar de strpos
.
substr_replace
es una función algo difícil de manejar debido a todos los parámetros, el problema real es que hacer la manipulación de cadenas por números a veces es complicado : debe tener cuidado de pasar la variable / desplazamiento correcto a las funciones. De hecho, iría tan lejos como para decir que el código anterior es el enfoque más directo y, para mí, lógico.
Editar: ambas respuestas se han actualizado y ahora son correctas. Dejaré la respuesta ya que los tiempos de la función siguen siendo útiles.
Lamentablemente, las respuestas de 'zombat' y 'demasiado php' no son correctas. Esta es una revisión de la respuesta publicada por zombat (ya que no tengo suficiente reputación para publicar un comentario):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Tenga en cuenta el strlen ($ aguja), en lugar de strlen ($ replace). El ejemplo de Zombat solo funcionará correctamente si la aguja y el reemplazo tienen la misma longitud.
Aquí está la misma funcionalidad en una función con la misma firma que el propio str_replace de 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;
}
Esta es la respuesta revisada de 'demasiado php':
implode($replace, explode($search, $subject, 2));
Tenga en cuenta el 2 al final en lugar de 1. O en formato de función:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Tomé el tiempo de las dos funciones y la primera es el doble de rápido cuando no se encuentra ninguna coincidencia. Tienen la misma velocidad cuando se encuentra una coincidencia.
stripos()
al rescate :-)
Me preguntaba cuál era el más rápido, así que los probé a todos.
Abajo encontrarás:
Todas las funciones se probaron con la misma configuración:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Funciones que solo reemplazan la primera aparición de una cadena dentro de una cadena:
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%
Funciones que solo reemplazan la última aparición de una cadena dentro de una cadena:
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()
gana el resultado es simple; porque es una función interna. Dos funciones internas y definidas por el usuario que hacen lo mismo difieren en rendimiento, porque la interna se ejecuta en capas inferiores. Entonces, ¿por qué no preg_match()
? Las expresiones regulares son casi más lentas que todas las funciones internas de manipulación de cadenas, debido a su nación de búsqueda en una cadena varias veces.
substr_replace($string, $replace, 0, strlen($search));
) no haya escrito simplemente esa estática 0
. Parte de la convolución de las soluciones que no son expresiones regulares es que necesitan "encontrar" el punto de partida antes de saber dónde reemplazar.
Desafortunadamente, no conozco ninguna función PHP que pueda hacer esto.
Puede rodar el suyo con bastante facilidad de esta manera:
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));
para números de reemplazo personalizados
Creé esta pequeña función que reemplaza cadena en cadena (distingue entre mayúsculas y minúsculas) con límite, sin la necesidad de Regexp. Funciona bien.
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;
}
Ejemplo de uso:
$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
lugar de is_bool(
ser más explícito, ¡doy este visto bueno porque ha evitado la locura de RegExp ! ... y al mismo tiempo funciona y es una solución limpia ...
preg_
solución fácilmente personalizable no es una locura, sino una preferencia personal. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
es bastante simple de leer para las personas que no temen a las expresiones regulares. ¿Necesita una búsqueda que no distinga entre mayúsculas y minúsculas? Agregue i
después del delimitador de patrón final. ¿Necesita soporte unicode / multibyte? Agregue u
después del delimitador de patrón final. ¿Necesita soporte de límite de palabra? Agregue \b
a ambos lados de su cadena de búsqueda. Si no quieres regex, no uses regex. Caballos para cursos, pero ciertamente no locura.
La forma más fácil sería usar expresiones regulares.
La otra forma es encontrar la posición de la cadena con strpos () y luego un substr_replace ()
Pero realmente iría por el 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));
}
=> EL CÓDIGO FUE REVISADO, así que considera algunos comentarios demasiado viejos
Y gracias a todos por ayudarme a mejorar eso
Cualquier error, por favor comuníqueme; Lo arreglaré justo después
Entonces, vamos por:
Reemplazando la primera 'o' por 'ea' por ejemplo:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
La función:
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))
, no substr($where,$b+1)
. Y supongo que eso substr_replace
es más rápido.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
de $find
antes de utilizarlo como una expresión.
preg_quote()
esta respuesta duplicado tarde se puede purgar de forma segura desde la página debido a que su consejo es proporcionada por el anterior, y la respuesta aceptada mayor upvoted..
Para ampliar la respuesta de @ renocor , he escrito una función que es 100% compatible con versiones anteriores str_replace()
. Es decir, se puede reemplazar todas las ocurrencias de str_replace()
la str_replace_limit()
sin jugar a nada, incluso aquellos que utilizan matrices para el $search
, $replace
y / o$subject
.
La función podría ser completamente autónoma, si quisiera reemplazar la llamada a la función ($string===strval(intval(strval($string))))
, pero lo recomendaría, ya que valid_integer()
es una función bastante útil cuando se trata de enteros proporcionados como cadenas.
Nota: Siempre que sea posible, str_replace_limit()
se utilizará str_replace()
en su lugar, por lo que todas las llamadas a str_replace()
se pueden reemplazarstr_replace_limit()
sin preocuparse por un golpe en el rendimiento.
<?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 reemplazos - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 reemplazos - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 reemplazos - 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
todo momento, lo cual es una advertencia , no un error . La traza inversa es extremadamente útil para averiguar qué código está pasando los datos no válidos a la función en primer lugar (que es absolutamente necesario para rastrear errores en la producción). En cuanto a regresar en $subject
lugar de false
/ null
o arrojar un error, esa fue simplemente una elección personal para mi caso de uso. Para igualar str_replace()
la funcionalidad, el uso de errores fatales detectables sería la mejor opción (como lo str_replace()
es cuando se proporciona un cierre para los dos primeros argumentos).
preg_replace()
. Además, preg_replace()
/ regex ofrece manejo de límites de palabras (si lo desea), algo que las funciones que no son expresiones regulares no proporcionarán con elegancia.
De acuerdo con el resultado de mi prueba, me gustaría votar el regular_express proporcionado por karim79. (¡No tengo suficiente reputación para votarlo ahora!)
La solución de zombat usa demasiadas llamadas a funciones, incluso simplifico los códigos. Estoy usando PHP 5.4 para ejecutar ambas soluciones 100,000 veces, y aquí está el resultado:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1.85 segundos
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1.35 segundos
Como puedes ver. El rendimiento de preg_replace no es tan malo como mucha gente piensa. Por lo tanto, sugeriría la solución con clase si su expreso regular no es complicado.
$pos
buscando false
, por lo que cuando la aguja no existe en el pajar, dañará la salida.
Para ampliar la respuesta de zombat (que creo que es la mejor respuesta), creé una versión recursiva de su función que incluye un $limit
parámetro para especificar cuántas ocurrencias desea reemplazar.
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
, por lo que si está más allá de la longitud de la cadena, esta función generará: Warning: strpos(): Offset not contained in string...
. Esta función no puede hacer un reemplazo cuando $start_pos
está más allá de la longitud. Prueba de falla: 3v4l.org/qGuVIR ... Su función puede combinar las return $haystack
condiciones y evitar declarar variables de un solo uso como esta: 3v4l.org/Kdmqp Sin embargo, como he dicho en comentarios en otra parte de esta página, prefiero use una preg_replace()
llamada muy limpia, directa y no recursiva .
else
declaración de línea$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Para una cuerda
$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
Para un solo personaje
$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()
técnicas dañan la cadena de entrada cuando el valor de búsqueda no está presente. Prueba de falla: 3v4l.org/HmEml (Y esa última técnica con todas las rev
llamadas es seriamente complicada / dura para los ojos.)
Complementando lo que dijo la gente, recuerde que toda la cadena es una matriz:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á
. Demostración de fracaso
string
es una cadena multibyte usandomb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Usando substr_replace podemos reemplazar la aparición del primer carácter solo en cadena. como & se repite varias veces pero solo en la primera posición tenemos que reemplazar & con?
Esta función está fuertemente inspirada en la respuesta de @renocor. Hace que la función multi byte sea segura.
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;
}
Puedes usar esto:
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;
}
Encontré este ejemplo de php.net
Uso:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Salida:
ThiZ iz an examplz
Esto puede reducir un poco el rendimiento, pero es la solución más fácil.
strpos()
). Vota abajo porque no agrega ningún valor nuevo a la página.
Si su cadena no contiene caracteres multibyte y si desea reemplazar solo un carácter, simplemente puede usar strpos
Aquí una función que maneja errores
/**
* 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;
}
Para solución de bucle
<?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;
}
Aquí hay una clase simple que creé para envolver nuestro str_replace () ligeramente modificado funciones .
Nuestra función php :: str_rreplace () también le permite llevar a cabo un str_replace () inverso y limitado que puede ser muy útil cuando se trata de reemplazar solo las instancias X finales de una cadena.
Estos ejemplos usan 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")
Hay un espacio adicional más, pero en mi caso no importó, ya que era para el script de fondo.
Esta es mi primera respuesta aquí, espero hacerlo correctamente. ¿Por qué no usar el cuarto argumento de la función str_replace para este problema?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
recuento: si se aprueba, se establecerá en el número de reemplazos realizados.
editar: esta respuesta es incorrecta, porque el cuarto parámetro de str_replace es una variable a la que se le asigna el número de reemplazos realizados. Esto es inconsistente con preg_replace , que tiene un cuarto parámetro $limit
y un quinto parámetro &$count
.
Es fácil encontrar una solución para reemplazar solo la primera o la primera pareja de instancias (dando el valor de conteo). No hay muchas soluciones para reemplazar el último o el último par de instancias.
Tal vez algo como str_replace ($ find, $ replace, $ subject, -3) debería reemplazar las últimas tres instancias.
De todos modos, solo una sugerencia.
s($subject)->replaceFirst($search)
ys($subject)->replaceFirstIgnoreCase($search)
útil, como se encuentra en esta biblioteca independiente .