rubyguides

String#replace

str.replace(other_str) -> str

The replace method swaps out a string’s entire contents with another string. Unlike sub or gsub that substitute portions matching a pattern, replace discards everything and fills the string with new content.

What makes replace unusual is that it mutates in place and returns self - the same object, not a copy. The object’s identity stays the same.

Syntax

str.replace(other_str) -> str

Parameters

ParameterTypeDescription
other_strStringThe string to copy into self

Return Value

Returns self (the same string object, now holding different content). This is different from most string methods that return new objects.

Examples

Basic Usage

s = "hello"
s.replace("world")
s # => "world"

Returns Self, Not a Copy

s1 = "original"
s2 = s1.replace("modified")
s1.object_id == s2.object_id  # => true (same object)

This matters when multiple variables point to the same string. After replace, all variables see the new value. After reassignment, they don’t.

Self-Assignment Is a No-Op

s = "hello"
s.replace(s)  # => "hello" — no change, returns immediately

The method checks for self-assignment and returns without modifying.

Frozen Strings Raise Error

s = "hello".freeze
s.replace("world")  # => FrozenError (Ruby 2.5+)

Behavior Details

Object Identity Is Preserved

replace mutates the string in place and returns self — it does not create a copy. The object_id doesn’t change. You’re not replacing the object, you’re replacing what the object contains:

buffer = "initial"
id = buffer.object_id
buffer.replace("changed")
buffer.object_id == id  # => true

This is useful for reusable string buffers where you want to avoid allocations.

Taintedness Transfers

If the replacement string is tainted, the target becomes tainted:

s = "hello"
s.replace("world".taint)
s.tainted?  # => true

Encoding Changes to Match Source

The encoding of self becomes the encoding of other_str:

s = "hello".encode("ASCII-8BIT")
s.replace("world".encode("UTF-8"))
s.encoding  # => #<Encoding:UTF-8>

Common Patterns

Reusable String Buffer

def build_response(buffer, status, body)
  buffer.replace("HTTP/1.1 #{status}\r\n")
  buffer.replace(buffer + "\r\n#{body}")
end

buf = String.new
build_response(buf, 200, "OK")

In-Place Normalisation

def normalise!(str)
  str.replace(str.strip.downcase)
end

data = "  Hello World  "
normalise!(data)
data  # => "hello world"

Edge Cases

  • Frozen string: Raises FrozenError — you can’t modify a frozen string
  • Self-assignment: Returns immediately with no changes
  • Empty string: Works fine - effectively clears the string
  • Non-string argument: Calls StringValue() which coerces via to_s

See Also

  • String#sub — Replace first pattern match (returns new string)
  • String#gsub! — Replace all pattern matches in place
  • String#tr — Character-by-character translation

Written

  • File: sites/rubyguides/src/content/reference/string-methods/string-replace.md
  • Words: ~380
  • Read time: 2 min
  • Topics covered: replace method, mutation, object identity, frozen strings, taintedness, encoding
  • Verified via: docs.ruby-lang.org/en/3.4/String.html, research.md artifact
  • Unverified items: exact encoding behavior details (not deeply verified)