PHP Reemplazar la última aparición de una cadena en una cadena?

Respuestas:

228

Puedes usar esta función:

function str_lreplace($search, $replace, $subject)
{
    $pos = strrpos($subject, $search);

    if($pos !== false)
    {
        $subject = substr_replace($subject, $replace, $pos, strlen($search));
    }

    return $subject;
}
Mischa
fuente
Esto seguía volviendo cierto, no importa qué. Considere modificarlo para que sea: if ($ pos) {$ subject = substr_replace ($ subject, $ replace, $ pos, strlen ($ search)); devolver $ sujeto; } else {return false; }
Jazzy
44
@ Jason No vuelve, pase lo que pase TRUE. Devuelve una cadena sin importar qué. Si no se puede hacer un reemplazo, devuelve el original $subject, al igual que substr_replace y str_replacehacer.
Mischa
@Mischa ¿No es lo mismo en este caso? Estaba intentando hacer algo como! Str_lreplace, pero si no devuelve falso, se considera cierto, ¿verdad? De cualquier manera, esto me ayudó y lo aprecio. Gracias.
Jazzy
1
¿Cómo puede funcionar esto? strpos — Find the position of the first occurrence of a substring in a string- editar: wow Los genios de PHP realmente hicieron una función llamada strposy strrpos? Gracias ....
BarryBones41
1
@Barry, este es un caso en el que PHP no merece la culpa :-) Los nombres están modelados en las décadas de antigüedad strstr, strrstrde la biblioteca C estándar, que son las mismas funciones. (¿Pero que tienen que cambiar el nombre?)
Alexis
30

Otro 1-liner pero sin preg:

$subject = 'bourbon, scotch, beer';
$search = ',';
$replace = ', and';

echo strrev(implode(strrev($replace), explode(strrev($search), strrev($subject), 2))); //output: bourbon, scotch, and beer
ricka
fuente
3
FWIW, la solución aceptada es aproximadamente un 35% más rápida que esta solución.
JustCarty
27
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace(strrev("/$find/"),strrev($replace),strrev($string),1);
echo strrev($result); //output: this is my world, not my farm
zack
fuente
La mejor solución en mi opinión y aún fácil de entender.
Blackbam
¿Por qué funciona con todas las cadenas invertidas? ¿Hay alguna (supongo) ganancia de rendimiento específica cuando se usan expresiones regulares?
Kamafeather
No, en realidad disminuye el rendimiento, pero se debe a que solo quieres la última aparición, así que limitas la búsqueda a una y reviertes todo si quisieras lo primero, no tendrías que revertir nada
Tofandel
15

La siguiente solución bastante compacta utiliza la afirmación de búsqueda anticipada positiva de PCRE para que coincida con la última aparición de la subcadena de interés, es decir, una aparición de la subcadena que no es seguida por ninguna otra aparición de la misma subcadena. Así, el ejemplo reemplaza el last 'fox'con 'dog'.

$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!';
echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);

SALIDA: 

The quick brown fox, fox, fox jumps over the lazy dog!!!
John Sonderson
fuente
55
La idea es buena, pero el código no lo es. Debe ser:$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!'; echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);
Roemer
De hecho, el código que publiqué cambia todas las instancias de "zorro" excepto el último "perro", pero lo que queremos es exactamente lo contrario. Gracias por señalar que reemplazar? = Con?! soluciona el problema
John Sonderson
11

Podrías hacer esto:

$str = 'Hello world';
$str = rtrim($str, 'world') . 'John';

El resultado es 'Hola John';

Saludos

Nicolas Finelli
fuente
44
Esto funciona siempre que no haya caracteres repetidos. En mi situación, estoy quitando el número de página de la fecha de archivo, así que tengo "2015-12 / 2" y quita todo / y todos los 2 al final convirtiéndose en "2015-1".
Mike
Esto solo funcionará si la última aparición buscada es la última palabra y no tiene caracteres adicionales después.
AwesomeGuy
Esto no funciona porque rtrimno se comporta de la manera que estás pensando. Eliminará desde el final cualquier carácter que exista en la cadena de búsqueda en cualquier orden (y siempre adjuntará el reemplazo), por ejemplo, "Hola palabra" -> "Hola John", "Hola señor" -> "Hola John", "Hola motor "->" Hello motJohn "," Hello worldy "->" Hello worldyJohn ".
Jake
5

Esto también funcionará:

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '(.*?)~', '$1' . $replace . '$2', $subject, 1);
}

ACTUALIZACIÓN Versión ligeramente más concisa ( http://ideone.com/B8i4o ):

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1);
}
Alix Axel
fuente
¿Lo estoy haciendo mal? Si es así, solo ignórame :) ||| echo str_lreplace ("x", "y", "this x or that x"); => Salida: "y" Ver: ideone.com/UXuTo
edorian
@edorian: ¡Uy! Lo siento, publiqué que a toda prisa, la versión correcta está aquí: ideone.com/vR073 .
Alix Axel
5

Solo una línea de código (respuesta tardía pero vale la pena agregarlo):

$string = 'The quick brown fox jumps over the lazy dog';
$find_me = 'dog';

preg_replace('/'. $find_me .'$/', '', $string);

el final $ indica el final de la cadena.

Franco
fuente
5

Esta es una pregunta antigua, pero ¿por qué todos pasan por alto la solución más simple basada en expresiones regulares? ¡Los cuantificadores normales de expresiones regulares son codiciosos, gente! Si desea encontrar la última instancia de un patrón, simplemente quédese .*frente a él. Así es cómo:

$text = "The quick brown fox, fox, fox, fox, jumps over etc.";
$fixed = preg_replace("((.*)fox)", "$1DUCK", $text);
print($fixed);

Esto reemplazará la última instancia de "zorro" a "PATO", como se supone que debe hacerlo, e imprimirá:

The quick brown fox, fox, fox, DUCK, jumps over etc.
alexis
fuente
1
¡Gracias! La función perfecta para envolver mi expresión para lograr esto. En mi caso, estoy reemplazando la última coma con ", y". Me alegro de haberme desplazado un poco hacia abajo en esta lista de respuestas.
Rlhane
3
$string = "picture_0007_value";
$findChar =strrpos($string,"_");
if($findChar !== FALSE) {
  $string[$findChar]=".";
}

echo $string;

Además de los errores en el código, Faruk Unal tiene la mejor respuesta. Una función hace el truco.

xwero
fuente
Debe verificar si $ findChar no es falso (de la misma manera que en la respuesta aceptada). Si la cadena no contiene la cadena buscada, recibirá un aviso y el primer carácter será reemplazado.
peludo
Esto es genial, pero tal como está, solo puede reemplazar 1 personaje con 1 personaje.
Pete
3

Puede usar strrpos () para encontrar la última coincidencia.

$string = "picture_0007_value";
$findChar =strrpos($string,"_");

$string[$findChar]=".";

echo $string;

Salida: picture_0007.value

Faruk ÜNAL
fuente
2

Taquigrafía para la respuesta aceptada

function str_lreplace($search, $replace, $subject){ 
    return is_numeric($pos=strrpos($subject,$search))?
    substr_replace($subject,$replace,$pos,strlen($search)):$subject;
}
Abbas
fuente
2

Una versión corta:

$NewString = substr_replace($String,$Replacement,strrpos($String,$Replace),strlen($Replace));
Jeffrey la jirafa
fuente
0

Use el "$" en una expresión reg para que coincida con el final de la cadena

$string = 'The quick brown fox jumps over the lazy fox';
echo preg_replace('/fox$/', 'dog', $string);

//output
'The quick brown fox jumps over the lazy dog'
Neil Holcomb
fuente
44
esto funciona solo si la última ocurrencia está al final de la cadena ideone.com/nbNSNq
cawecoy
1
Esto no funcionará si aparecen otros personajes después del último 'zorro'.
John Sonderson
0

Para los interesados: he escrito una función que utiliza preg_match para que pueda reemplazar desde el lado derecho usando regex.

function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    $lastMatch = end($matches);

    if ($lastMatch && false !== $pos = strrpos($subject, $lastMatchedStr = $lastMatch[0])) {
        $subject = substr_replace($subject, $replace, $pos, strlen($lastMatchedStr));
    }

    return $subject;
}

O como una combinación / implementación abreviada de ambas opciones:

function str_rreplace($search, $replace, $subject) {
    return (false !== $pos = strrpos($subject, $search)) ?
        substr_replace($subject, $replace, $pos, strlen($search)) : $subject;
}
function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    return ($lastMatch = end($matches)) ? str_rreplace($lastMatch[0], $replace, $subject) : $subject;
}

basado en https://stackoverflow.com/a/3835653/3017716 y https://stackoverflow.com/a/23343396/3017716

Conocido
fuente