String#sub
str.sub(pattern, replacement) -> string String#sub replaces only the first occurrence of a pattern in a string. It returns a new string with just the first match replaced by the replacement. Use this when you only need to replace the first occurrence.
That first-match behavior is the part that makes sub feel precise. It lets you change a prefix, clean up a header, or normalize a single pattern without touching the rest of the text. When you only want one substitution, sub keeps the code easier to read than a manual scan plus index math. If every match should change, reach for gsub instead and let the method name match the scope of the edit.
The examples below move from plain string replacement to regex, hash, and block forms. That mix is useful because sub behaves the same way in each case, but the match logic changes enough that it helps to see the options side by side.
Syntax
str.sub(pattern, replacement)
str.sub(pattern) { |match| block }
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
pattern | String or Regexp | — | The substring or pattern to find and replace |
replacement | String, Hash, or nil | — | The replacement text, hash of substitutions, or nil when using a block |
Examples
Basic string replacement
text = "hello world"
text.sub("world", "Ruby")
# => "hello Ruby"
The basic replacement shows sub at its simplest: a direct string-for-string swap. When the pattern appears multiple times in the source text, the method still only touches the first one it finds. That is the central difference between sub and gsub, and understanding it early helps you pick the right method for the job. The next example makes this single-match behavior explicit by repeating the search term twice in the source and showing that only the first instance changes.
Replacing only first occurrence
text = "hello world hello"
text.sub("hello", "goodbye")
# => "goodbye world hello"
Note the difference from gsub: only the first “hello” is replaced.
This is the simplest way to see the method’s scope. If the first match is the only one that matters, the rest of the string stays untouched and the example reads almost like a sentence.
Using regex patterns
phone = "(555) 123-4567"
phone.sub(/\(\d{3}\)\s*/, "")
# => "123-4567" (only first pattern removed if multiple)
text = "one two three"
text.sub(/\w+/) { |word| word.upcase }
# => "ONE two three" (only first word transformed)
The regex form is still limited to a single replacement, so the pattern can be as broad as you need without changing the rest of the text. That keeps the method useful for first-token cleanup and similar one-off edits.
Using a hash for replacement
replacements = { "cat" => "dog", "run" => "walk" }
"cat run".sub(/cat|run/, replacements)
# => "dog run" (only first match replaced)
Hash replacement is handy when the first match should map to a known substitute and nothing more. It reads well when the replacement table is already part of the surrounding code. The hash form is especially useful in text-processing pipelines where a fixed set of abbreviations or codes needs to be expanded on the first encounter, with the rest of the string staying as-is.
Working with capture groups
"first last".sub(/(\w+) (\w+)/, '\2, \1')
# => "last, first"
"hello".sub(/[aeiou]/) { |v| v.upcase }
# => "hEllo" (only first vowel replaced)
The capture-group form is most useful when the replacement needs to be assembled from the match itself. Even then, sub keeps the scope tight, which is what makes it a good fit for small targeted edits.
Common patterns
- Replace the first occurrence with
text.sub("old", "new"). - Remove the first character with
text.sub(/^./, ""). - Capitalize the first letter with
text.sub(/[a-z]/) { |c| c.upcase }. - Normalize the first whitespace run with
text.sub(/\s+/, " ").
Those examples cover the main shapes you are likely to use in real code. The key idea is always the same: one match changes, and the rest of the string stays exactly as it was.
Errors
- No pattern given: Raises
ArgumentErrorif neither pattern nor block is provided. - String interpolation in replacement: Remember to escape
\1,\2when using double-quoted strings, or use single quotes.
Performance notes
sub is faster than gsub when you only need to replace the first occurrence, as it stops after the first match.
That small difference matters in cleanup code where the first match is the only one that needs attention. It is also a useful signal to the reader because the method choice says that the rest of the string should stay exactly as it is.
When you see sub, think “single edit” instead of “general replacement.” That mental shortcut makes the method easier to reach for when the code only needs one precise change.