rubyguides

String#sub

String#sub replaces the first occurrence of a pattern in a string. It returns a new string and leaves the original unchanged.

Signature

str.sub(pattern, replacement)
str.sub(pattern) { |match| block }

Parameters:

  • pattern — a String or Regexp to search for
  • replacement — a String (optional), or a block that returns the replacement

Returns: A new string with the replacement made.

Basic String Replacement

Replace one substring with another:

"hello".sub("l", "x")       # => "hexlo"
"hello".sub("lo", "p")      # => "help"

Only the first match is replaced:

"hello".sub("l", "x")       # => "hexlo"  (not "hexxo")

Regexp Patterns

Use a regexp for more control:

"hello123".sub(/\d+/, "world")   # => "helloworld"
"hello123".sub(/[aeiou]/, "*")    # => "h*llo"

Anchors work as expected:

"hello".sub(/^h/, "H")           # => "Hello"
"hello".sub(/o$/, "O")           # => "hellO"

Capture Groups

Capture groups let you reuse parts of the matched text:

"hello".sub(/(ello)/, "good-\1")  # => "good-ello"

Numbered groups work with backreferences:

"first second".sub(/(\w+) (\w+)/, '\2 \1')  # => "second first"

Named capture groups:

"john doe".sub(/(?<first>\w+) (?<last>\w+)/, '\k<last>, \k<first>')
# => "doe, john"

Using a Block

When you pass a block instead of a replacement string, the block receives the match and returns the replacement:

"hello".sub(/[aeiou]/) { |v| v.upcase }  # => "hEllo"

This is useful for transformations:

"price: 42".sub(/\d+/) { |n| "$#{n}" }   # => "price: $42"

The block gets the full match. Only the first match is replaced.

Special Replacement Patterns

Within a replacement string, these patterns have special meaning:

PatternMeaning
\&The entire matched string
\The part before the match
\'The part after the match
\1 \2Numbered capture groups
\\A literal backslash
"hello".sub("l", "(&)")     # => "he(l)lo"
"hello".sub("l", "$\`")    # => "hehe lo"
"hello".sub("l", "$\'")    # => "helo lo"

Deleting Characters

Combine sub with an empty replacement to delete:

"hello!".sub("!", "")      # => "hello"
"  hello  ".sub(" ", "")   # => " hello  " (only first space)

For deleting all occurrences, use gsub instead.

Comparison with gsub

sub replaces only the first match. gsub replaces all matches:

"hello".sub("l", "x")      # => "hexlo"
"hello".gsub("l", "x")     # => "hexxo"

See Also