[php] Replace last occurrence of a string in a string

Anyone know of a very fast way to replace the last occurrence of a string with another string in a string?

Note, the last occurrence of the string might not be the last characters in the string.

Example:

$search = 'The';
$replace = 'A';
$subject = 'The Quick Brown Fox Jumps Over The Lazy Dog';

Expected Output:

The Quick Brown Fox Jumps Over A Lazy Dog

This question is related to php string replace last-occurrence

The answer is


The following rather compact solution uses the PCRE positive lookahead assertion to match the last occurrence of the substring of interest, that is, an occurrence of the substring which is not followed by any other occurrences of the same substring. Thus the example replaces the last 'fox' with 'dog'.

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

OUTPUT: 

The quick brown fox, fox, fox jumps over the lazy dog!!!

$string = "picture_0007_value";
$findChar =strrpos($string,"_");
if($findChar !== FALSE) {
  $string[$findChar]=".";
}

echo $string;

Apart from the mistakes in the code, Faruk Unal has the best anwser. One function does the trick.


This will also work:

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

UPDATE Slightly more concise version (http://ideone.com/B8i4o):

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

For the interested: I've written a function that utilises preg_match so that you're able to replace from right hand side using 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;
}

Or as a shorthand combination/implementation of both 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;
}

based on https://stackoverflow.com/a/3835653/3017716 and https://stackoverflow.com/a/23343396/3017716


Another 1-liner but without preg:

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

echo strrev(implode(strrev($replace), explode(strrev($search), strrev($subject), 2))); //output: bourbon, scotch, and beer

Use the "$" on a reg expression to match the end of the string

$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'

A short version:

$NewString = substr_replace($String,$Replacement,strrpos($String,$Replace),strlen($Replace));

While using regex is typically less performant than non-regex techniques, I do appreciate the control and flexibility that it affords.

In my snippet, I will set the pattern to be case-insensitive (\i, although my sample input will not challenge this rule) and include word boundaries (\b, although they were not explicitly called for).

I am also going to use the \K metacharacter to reset the fullstring match so that no capture groups / backreferences are needed.

Code: (Demo)

$search = 'The';
$replace = 'A';
$subject = "The Quick Brown Fox Jumps Over The Lazy Dog's Thermos!";

echo preg_replace(
         '/.*\K\b' . preg_quote($search, '/') . '\b/i',
         $replace,
         $subject
     );

Output:

  The Quick Brown Fox Jumps Over A Lazy Dog's Thermos!
# ^^^                            ^            ^^^
# not replaced                replaced        not replaced

Without word boundaries: (Demo)

echo preg_replace(
         '/.*\K' . preg_quote($search, '/') . '/i',
         $replace,
         $subject
     );

Output:

  The Quick Brown Fox Jumps Over The Lazy Dog's Armos!
# ^^^                            ^^^            ^
# not replaced              not replaced        replaced

This is an ancient question, but why is everyone overlooking the simplest regexp-based solution? Normal regexp quantifiers are greedy, people! If you want to find the last instance of a pattern, just stick .* in front of it. Here's how:

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

This will replace the last instance of "fox" to "DUCK", like it's supposed to, and print:

The quick brown fox, fox, fox, DUCK, jumps over etc.

$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

You could do this:

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

Result is 'Hello John';

Regards


Shorthand for accepted answer

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

You can use strrpos() to find last match.

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

$string[$findChar]=".";

echo $string;

Output : picture_0007.value


Below corrected zack's code (https://stackoverflow.com/a/11144999/9996503). Be careful with regular expressions! Consider this:

$string = 'Round brackets (parentheses) "()", square brackets "()"';
$find = '()';
$replace = '[]';
// Zack's code:
$result = preg_replace(strrev("/$find/"),strrev($replace),strrev($string),1);
var_dump($result); // Output: NULL
// Correct code:
$result = strrev(preg_replace('/'.preg_quote(strrev($find)).'/', strrev($replace), strrev($string), 1));
echo $result; //Output: Round brackets (parentheses) "()", square brackets "[]"

Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to replace

How do I find and replace all occurrences (in all files) in Visual Studio Code? How to find and replace with regex in excel How to replace text in a column of a Pandas dataframe? How to replace negative numbers in Pandas Data Frame by zero Replacing few values in a pandas dataframe column with another value How to replace multiple patterns at once with sed? Using tr to replace newline with space replace special characters in a string python Replace None with NaN in pandas dataframe Batch script to find and replace a string in text file within a minute for files up to 12 MB

Examples related to last-occurrence

Replace last occurrence of a string in a string