How to replace the last occurrence of a substring in ruby?

How about

new_str = old_str.reverse.sub(pattern.reverse, replacement.reverse).reverse

For instance:

irb(main):001:0> old_str = "abc123abc123"
=> "abc123abc123"
irb(main):002:0> pattern="abc"
=> "abc"
irb(main):003:0> replacement="ABC"
=> "ABC"
irb(main):004:0> new_str = old_str.reverse.sub(pattern.reverse, replacement.reverse).reverse
=> "abc123ABC123"

"abc123abc123".gsub(/(.*(abc.*)*)(abc)(.*)/, '\1ABC\4')
#=> "abc123ABC123"

But probably there is a better way...

Edit:

...which Chris kindly provided in the comment below.

So, as * is a greedy operator, the following is enough:

"abc123abc123".gsub(/(.*)(abc)(.*)/, '\1ABC\3')
#=> "abc123ABC123"

Edit2:

There is also a solution which neatly illustrates parallel array assignment in Ruby:

*a, b = "abc123abc123".split('abc', -1)
a.join('abc')+'ABC'+b
#=> "abc123ABC123"

Since Ruby 2.0 we can use \K which removes any text matched before it from the returned match. Combine with a greedy operator and you get this:

'abc123abc123'.sub(/.*\Kabc/, 'ABC')
#=> "abc123ABC123"

This is about 1.4 times faster than using capturing groups as Hirurg103 suggested, but that speed comes at the cost of lowering readability by using a lesser-known pattern.

more info on \K: https://www.regular-expressions.info/keep.html

Tags:

Ruby