335

I have a string in Ruby:

sentence = "My name is Robert"

How can I replace any one word in this sentence easily without using complex code or a loop?

Blubber
  • 1,375
  • 1
  • 15
  • 32
Mithun Sasidharan
  • 20,572
  • 10
  • 34
  • 52
  • Replace in what way? Replace an arbitrary word (word #2), or a specific word (`my`)? – Blender Dec 05 '11 at 05:56
  • Thanks for your short, simple and useful question. it helped me out finding a solution to style hashtags in my view – Stef Hej May 15 '16 at 16:54

4 Answers4

568
sentence.sub! 'Robert', 'Joe'

Won't cause an exception if the replaced word isn't in the sentence (the []= variant will).

How to replace all instances?

The above replaces only the first instance of "Robert".

To replace all instances use gsub/gsub! (ie. "global substitution"):

sentence.gsub! 'Robert', 'Joe'

The above will replace all instances of Robert with Joe.

lucasarruda
  • 1,462
  • 1
  • 25
  • 45
srcspider
  • 10,977
  • 5
  • 40
  • 35
  • This seems to replace only the first instance, which is of course sometimes fine and sometimes not. – Jason Swett Sep 18 '13 at 19:57
  • 1
    @JasonSwett updated the answer to cover how to replace all instances. – srcspider Sep 19 '13 at 14:10
  • 4
    Just be careful when using `sub!` and `gsub!` on a string literals - the non-exclamation mark versions should be used instead. Strings literals will be immutable in Ruby 3 and this will raise an exception. – Itay Grudev Sep 02 '20 at 09:46
  • If you're looking to replace all occurrences with nothing (e.g. `""`) then you can also look at using `delete!( "Robert" )`. – Joshua Pinter Sep 22 '21 at 18:37
  • Like @ItayGrudev mentions, be aware that `.sub!` mutates `sentence`. You should might want to use just `.sub` instead – Jesper Johansson Jan 05 '22 at 09:47
  • Beware this will change "Robertino" to "Joeino", which is probably **not** want you want. – lulalala Jul 03 '22 at 15:32
172

If you're dealing with natural language text and need to replace a word, not just part of a string, you have to add a pinch of regular expressions to your gsub as a plain text substitution can lead to disastrous results:

'mislocated cat, vindicating'.gsub('cat', 'dog')
=> "mislodoged dog, vindidoging"

Regular expressions have word boundaries, such as \b which matches start or end of a word. Thus,

'mislocated cat, vindicating'.gsub(/\bcat\b/, 'dog')
=> "mislocated dog, vindicating"

In Ruby, unlike some other languages like Javascript, word boundaries are UTF-8-compatible, so you can use it for languages with non-Latin or extended Latin alphabets:

'сіль у кисіль, для весіль'.gsub(/\bсіль\b/, 'цукор')
=> "цукор у кисіль, для весіль"
CreeFC
  • 13
  • 4
Hnatt
  • 5,767
  • 3
  • 32
  • 43
  • 8
    Note that some languages don't even use spaces, so `\b` doesn't work in them, you would need to use morphological analyzers or stuff like that in those cases. Also, +1 for hilarious example. – NiñoScript Jul 26 '16 at 16:36
65

You can try using this way :

sentence ["Robert"] = "Roger"

Then the sentence will become :

sentence = "My name is Roger" # Robert is replaced with Roger
Mithun Sasidharan
  • 20,572
  • 10
  • 34
  • 52
  • 5
    That's pretty interesting. I've never seen this method of replacement before. – Sean Hill Dec 05 '11 at 06:03
  • 8
    Won't you get an error with this method if the original string doesn't contain the word you're trying to replace? – srcspider Jan 02 '13 at 15:59
  • 1
    I'm also interested in @srcspider's question – knocte Jan 09 '13 at 18:33
  • 2
    Just make sure to resuce on `IndexError`. Otherwise for a word not part of the sentence will lead to: `string not matched (IndexError)` – Konrad Reiche Mar 25 '13 at 09:43
  • That's really nice. Seems like Ruby is interrupting the string as a hash or array but changing the key instead the value. Could anyone tell this is a ordinary way of doing this? – gotqn Jul 01 '13 at 21:12
  • 11
    Another problem with this method is that it only replaces the first instance of the string. – Martin Konecny Jul 21 '13 at 19:00
  • 1
    Another problem with this method is when you use this in with activerecord. `u = User.first; u.name["black"] = "blue"; u.save!` won't save the change.. – JeroenKnoops Jan 09 '14 at 10:34
  • 21
    This is interesting, but should definitely not be marked as the correct answer. – Niels Abildgaard Aug 30 '14 at 13:11
  • Does this work without spaces? I suspect Ruby is converting to an array based on space delimiters – morefromalan Sep 17 '16 at 22:35
  • 1
    A quick fix for not having to rescue from `IndexError` is to check for if the word exists on string, like so: `string["Robert"] = "Roger" if string.include?("Robert")` – lucasarruda May 13 '17 at 16:57
51

First, you don't declare the type in Ruby, so you don't need the first string.

To replace a word in string, you do: sentence.gsub(/match/, "replacement").

Sean Hill
  • 14,978
  • 2
  • 50
  • 56