PHP Remplacer la dernière occurrence d'une chaîne dans une chaîne?

Réponses:

228

Vous pouvez utiliser cette fonction:

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

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

    return $subject;
}
Mischa
la source
Cela revenait toujours vrai quoi qu'il arrive. Pensez à le modifier comme suit: if ($ pos) {$ subject = substr_replace ($ subject, $ replace, $ pos, strlen ($ search)); return $ subject; } else {return false; }
Jazzy
4
@Jason Ça ne revient TRUEpas quoi qu'il arrive . Il renvoie une chaîne quoi qu'il arrive. Si un remplacement ne peut pas être effectué, il renvoie l'original $subject, tout comme substr_replace et str_replacefaire.
Mischa
@Mischa N'est-ce pas la même chose dans ce cas? J'essayais de faire quelque chose comme! Str_lreplace, mais s'il ne renvoie pas false, c'est considéré comme vrai, non? Quoi qu'il en soit, cela m'a aidé et je l'apprécie. Merci.
Jazzy
1
Comment cela peut-il fonctionner? strpos — Find the position of the first occurrence of a substring in a string- modifier: wow. Les génies de Php ont vraiment créé une fonction appelée strposet strrpos? Merci ....
BarryBones41
1
@Barry c'est un cas où PHP ne mérite pas le blâme :-) Les noms sont modelés sur les décennies strstr, strrstrde la bibliothèque C standard, qui sont les mêmes fonctions. (Mais ont-ils changer le nom?)
Alexis
30

Un autre 1-liner mais sans 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
la source
3
FWIW, la solution acceptée est environ 35% plus rapide que cette solution.
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
la source
La solution la plus cool à mon avis et toujours facile à comprendre.
Blackbam
Pourquoi cela fonctionne avec toutes les chaînes inversées? Y a-t-il un gain de performance spécifique (je suppose) lors de l'utilisation d'expressions régulières?
Kamafeather
Non, cela diminue les performances, mais c'est parce que vous ne voulez que la dernière occurrence, donc vous limitez la recherche à une seule et inversez tout si vous vouliez la première, vous n'auriez rien à inverser
Tofandel
15

La solution plutôt compacte suivante utilise l' assertion d'anticipation positive PCRE pour faire correspondre la dernière occurrence de la sous-chaîne d'intérêt, c'est-à-dire une occurrence de la sous-chaîne qui n'est suivie par aucune autre occurrence de la même sous-chaîne. Ainsi, l'exemple remplace le last 'fox'par 'dog'.

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

PRODUCTION: 

The quick brown fox, fox, fox jumps over the lazy dog!!!
John Sonderson
la source
5
L'idée est bonne, mais le code ne l'est pas. Il doit être:$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!'; echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);
Roemer le
En effet, le code que j'ai posté change toutes les instances de "fox" à l'exception de la dernière en "dog", mais ce que nous voulons c'est exactement le contraire. Merci d'avoir signalé que le remplacement de? = Par?! résout le problème.
John Sonderson
11

Vous pouvez faire ceci:

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

Le résultat est «Hello John»;

Cordialement

Nicolas Finelli
la source
4
Cela fonctionne tant qu'il n'y a pas de caractères répétés. Dans ma situation, j'enlève le numéro de page de la date d'archivage donc j'ai "2015-12 / 2" et cela prend tous / et tous les 2 à la fin devenant "2015-1".
Mike
Cela ne fonctionnera que si la dernière occurrence recherchée est le dernier mot et n'a pas de caractères supplémentaires après.
AwesomeGuy
Cela ne fonctionne pas car rtrimne se comporte pas comme vous le pensez. Il supprimera de la fin tous les caractères qui existent dans la chaîne de recherche dans n'importe quel ordre (et ajoutera toujours le remplacement), par exemple "Hello word" -> "Hello John", "Hello Lord" -> "Hello John", "Hello motor "->" Hello motJohn "," Hello worldy "->" Hello worldyJohn ".
Jake
5

Cela fonctionnera également:

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

MISE À JOUR Version légèrement plus concise ( http://ideone.com/B8i4o ):

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1);
}
Alix Axel
la source
Est-ce que je fais mal? Si c'est le cas, ignorez-moi :) ||| echo str_lreplace ("x", "y", "this x or that x"); => Sortie: "y" Voir: ideone.com/UXuTo
édorien
@edorian: Oups! Désolé, j'ai posté cela rapidement , la version correcte est ici: ideone.com/vR073 .
Alix Axel
5

Juste une ligne de code (réponse tardive mais cela vaut la peine de l'ajouter):

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

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

la fin $ indique la fin de la chaîne.

Franc
la source
5

C'est une question ancienne, mais pourquoi tout le monde néglige-t-il la solution la plus simple basée sur les expressions rationnelles? Les quantificateurs de regexp normaux sont gourmands, les gens! Si vous voulez trouver la dernière instance d'un motif, tenez-vous juste .*devant. Voici comment:

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

Cela remplacera la dernière instance de "renard" par "DUCK", comme il est censé le faire, et imprimera:

The quick brown fox, fox, fox, DUCK, jumps over etc.
Alexis
la source
1
Merci! La fonction parfaite pour envelopper mon expression pour accomplir cela. Dans mon cas, je remplace la dernière virgule par ", et". Heureux d'avoir fait défiler un peu cette liste de réponses.
rlhane
3
$string = "picture_0007_value";
$findChar =strrpos($string,"_");
if($findChar !== FALSE) {
  $string[$findChar]=".";
}

echo $string;

Hormis les erreurs de code, Faruk Unal a la meilleure réponse. Une fonction fait l'affaire.

xwero
la source
Vous devez vérifier si $ findChar n'est pas faux (de la même manière que dans la réponse acceptée). Si la chaîne ne contient pas la chaîne recherchée, vous obtenez un avis et le premier caractère sera remplacé.
shaggy
C'est génial, mais tel quel, il ne peut remplacer 1 caractère par 1 caractère.
Pete
3

Vous pouvez utiliser strrpos () pour trouver la dernière correspondance.

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

$string[$findChar]=".";

echo $string;

Sortie: picture_0007.value

Faruk ÜNAL
la source
2

Abréviation de la réponse acceptée

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

Une version courte:

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

Utilisez le "$" sur une expression reg pour correspondre à la fin de la chaîne

$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
la source
4
cela ne fonctionne que si la dernière occurrence est à la fin de la chaîne ideone.com/nbNSNq
cawecoy
1
Cela ne fonctionnera pas si d'autres caractères apparaissent après le dernier «renard».
John Sonderson
0

Pour les intéressés: j'ai écrit une fonction qui utilise preg_match afin que vous puissiez remplacer par le côté droit en utilisant 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;
}

Ou en tant que combinaison / implémentation des deux options:

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

basé sur https://stackoverflow.com/a/3835653/3017716 et https://stackoverflow.com/a/23343396/3017716

Ken
la source