Replace the last occurrence of a pattern in a JavaScript string
Replacing the first occurrence of a pattern in a string is easy, but what if you want to replace the last occurrence? This, admittedly, is a little trickier, especially if you want to match the functionality of String.prototype.replace()
.
First and foremost, we need to determine if the pattern
is a string or a regular expression. If it's a string, we can use it as the match
.
If it's a regular expression, we need to create a new regular expression using the RegExp()
constructor and the RegExp.prototype.source
of the pattern
, adding the 'g'
flag to it. Using String.prototype.match()
and Array.prototype.slice()
, we can then get the last match, if any.
We can then use String.prototype.lastIndexOf()
to find the last occurrence of the match in the string. If a match is found, we can use String.prototype.slice()
and a template literal to replace the matching substring with the given replacement
. If no match is found, we can simply return the original string.
Putting everything together results in a versatile implementation that can handle both strings and regular expressions, and that matches the functionality of String.prototype.replace()
:
const replaceLast = (str, pattern, replacement) => { const match = typeof pattern === 'string' ? pattern : (str.match(new RegExp(pattern.source, 'g')) || []).slice(-1)[0]; if (!match) return str; const last = str.lastIndexOf(match); return last !== -1 ? `${str.slice(0, last)}${replacement}${str.slice(last + match.length)}` : str; }; replaceLast('abcabdef', 'ab', 'gg'); // 'abcggdef' replaceLast('abcabdef', /ab/, 'gg'); // 'abcggdef' replaceLast('abcabdef', 'ad', 'gg'); // 'abcabdef' replaceLast('abcabdef', /ad/, 'gg'); // 'abcabdef'