tags:

views:

52

answers:

3

Hi guys,

I want to replace the last occurence of a substring in ruby. What's the most eastest way? For example, in abc123abc123, I want to replace the last abc to ABC. How can I did that?

+3  A: 

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"
Chris
+3  A: 
"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"
Mladen Jablanović
Due to greedy matching, just `str.sub(/(.*)abc/, '\1ABC')` should suffice.
Chris Johnsen
Doh! Thanks, I updated the answer.
Mladen Jablanović
Thank you very much. I also thought this problem can be solved by regular expression, but don't know how. You did it. Thanks again!
Yousui
+1  A: 
string = "abc123abc123"
pattern = /abc/
replacement = "ABC"

matches = string.scan(pattern).length
index = 0
string.gsub(pattern) do |match|
  index += 1
  index == matches ? replacement : match
end
#=> abc123ABC123
matsadler