String#gsub
String#gsub replaces every occurrence of a pattern in a string. The g means global — it replaces all matches, not just the first one. The original string is never modified.
Signature
str.gsub(pattern, replacement)
str.gsub(pattern) { |match| block }
Parameters:
pattern— a String or Regexpreplacement— a String, Hash, Symbol, or nil
Returns: String — a new string with all replacements
The bang variant gsub! modifies in place and returns the number of replacements, or nil if nothing matched.
String Pattern Replacement
"hello world".gsub("o", "0") # => "hell0 w0rld"
"a b a b a b".gsub("a", "X") # => "X b X b X b"
String patterns match literally — no regex features, just exact substring replacement.
Regex Pattern Replacement
"hello123world456".gsub(/\d+/, "NUMBER")
# => "helloNUMBERworldNUMBER"
"foo bar foo".gsub(/foo/, "baz")
# => "baz bar baz"
Regex patterns enable capture groups, character classes, and quantifiers.
Block Form
Pass a block and each match gets replaced with the block’s return value:
"hello world".gsub(/\w+/) { |word| word.upcase }
# => "HELLO WORLD"
"123-456-7890".gsub(/\d+/) { |n| n.to_i * 2 }
# => "246-912-15780"
The block receives the matched string. Whatever it returns becomes the replacement.
Backreferences
Use \1 through \9 in the replacement string to reference captured groups:
"John Doe".gsub(/(\w+) (\w+)/, '\2, \1')
# => "Doe, John"
"hello".gsub(/(.)/, '[\1]')
# => "[h][e][l][l][o]"
Named captures use \k<name>:
"John Doe".gsub(/(?<first>\w+) (?<last>\w+)/, '\k<last>, \k<first>')
# => "Doe, John"
Hash Replacement
Pass a Hash to substitute matches based on their content:
replacements = {
"hello" => "hi",
"world" => "earth",
"!" => "."
}
"hello world!".gsub(/\w+|!/, replacements)
# => "hi earth."
If a match has no key in the hash, it passes through unchanged.
Symbol as Replacement
A Symbol calls that method on the matched string:
"hello".gsub(/\w+/, :upcase) # => "HELLO"
"hello".gsub(/\w+/, :length) # => "5"
"hello world".gsub(/\w+/, :capitalize)
# => "Hello World"
Special Replacement Sequences
Some sequences in replacement strings have special meaning:
| Sequence | Becomes |
|---|---|
\\ | A literal backslash |
\n | Newline |
\t | Tab |
& | The entire matched string |
\` | The part before the match |
\' | The part after the match |
\+ | The last matched group |
"hello".gsub("ello", 'goodbye &')
# => "goodbye hello"
"world".gsub(/(world)/, 'hello, \\` & \\\'')
# => "hello, world"
The Bang Variant
gsub! modifies the string in place:
s = "hello world"
n = s.gsub!("o", "0")
s # => "hell0 w0rld"
n # => 2 (replacement count)
When nothing matches, gsub! returns nil:
s = "hello"
result = s.gsub!("x", "y")
result # => nil
Use gsub! when you need the replacement count or want to modify in place. Otherwise prefer gsub.
Counting Without Allocating a New String
count = 0
"hello world".gsub(/\w+/) { count += 1 }
count # => 2
gsub vs sub
| Method | Matches replaced | Returns |
|---|---|---|
sub | First only | New string |
gsub | All | New string |
sub! | First only | String or nil |
gsub! | All | String or nil |
Common Patterns
Normalizing Whitespace
"hello \n world".gsub(/\s+/, " ")
# => "hello world"
Redacting Words
sensitive = ["password", "secret", "token"]
replacements = Hash[sensitive.product(["[REDACTED]"]).to_h]
"use your password here".gsub(/\w+/, replacements)
# => "use your [REDACTED] here"
Converting Snake Case to CamelCase
"hello_world".gsub(/_(\w)/) { $1.upcase }
# => "helloWorld"
$1 is set by gsub’s block form, referencing the first capture group.
See Also
- /reference/string-methods/sub/ — replace only the first occurrence
- /reference/string-methods/replace/ — replace all content with new content
- /reference/string-methods/match/ — check if a pattern matches