Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace only the last match of a string with preg_replace?

I have to replace the last match of a string (for example the word foo) in HTML document. The problem is that the structure of the HTML document is always random.

I'm trying to accomplish that with preg_replace, but so far I know how to replace only the first match, but not the last one.

Thanks.

like image 815
Dimitur Vulchanov Avatar asked Oct 17 '11 07:10

Dimitur Vulchanov


2 Answers

Use negative look after (?!...)

$str = 'text abcd text text efgh';
echo preg_replace('~text(?!.*text)~', 'bar', $str),"\n";

output:

text abcd text bar efgh
like image 77
Toto Avatar answered Sep 28 '22 18:09

Toto


A common approach to match all text to the last occurrence of the subsequent pattern(s) is using a greedy dot, .*. So, you may match and capture the text before the last text and replace with a backreference + the new value:

$str = 'text abcd text text efgh';
echo preg_replace('~(.*)text~su', '${1}bar', $str);
// => text abcd text bar efgh

If text is some value inside a variable that must be treated as plain text, use preg_quote to ensure all special chars are escaped correctly:

preg_replace('~(.*)' . preg_quote($text, '~') . '~su', '${1}bar', $str)

See the online PHP demo and a regex demo.

Here, (.*) matches and captures into Group 1 any zero or more chars (note that the s modifier makes the dot match line break chars, too), as many as possible, up to the rightmost (last) occurrence of text. If text is a Unicode substring, the u modifier comes handy in PHP (it enables (*UTF) PCRE verb allowing parsing the incoming string as a sequence of Unicode code points rather than bytes and the (*UCP) verb that makes all shorthand character classes Unicode aware - if any).

The ${1} is a replacement backreference, a placeholder holding the value captured into Group 1 that lets restore that substring inside the resulting string. You can use $1, but a problem might arise if the $text starts with a digit.

like image 36
Wiktor Stribiżew Avatar answered Sep 28 '22 18:09

Wiktor Stribiżew