How to match all occurrences of a regular expression in Ruby?
In Ruby, you typically use the String#scan method to find all matches of a given regular expression in a string. For example:
text = "abc 123 def 456"
matches = text.scan(/\d+/)
# => ["123", "456"]
This returns an array containing all the substrings that match the regex. Below are more details and variations.
1. Basic Usage with String#scan
text = "Hello 123, goodbye 456"
pattern = /\d+/
results = text.scan(pattern)
p results
# Output: ["123", "456"]
text.scan(pattern)returns an array of all non-overlapping matches.
2. Capturing Groups
If your regex includes capturing groups, scan will return an array of arrays, each containing the capture groups for a match:
text = "first: 123, second: 456"
pattern = /(\w+):\s+(\d+)/
results = text.scan(pattern)
# => [["first", "123"], ["second", "456"]]
Here, each element is [group1, group2]. If your pattern had 3 capture groups, each element would have 3 elements, etc.
3. Processing Each Match with a Block
You can also pass a block to scan:
text = "abc 123 def 456"
text.scan(/\d+/) do |match|
puts "Found digits: #{match}"
end
- In this scenario,
scanstill iterates over all matches, but instead of returning an array, it will yield each match to the block.
4. Using match, =~, or match? for Single Occurrences
string.match(regex)returns the first match (as aMatchDataobject) ornil.string =~ regexreturns the 0-based index of the first match ornil.regex.match?(string)(Ruby 2.4+) quickly checks if there’s any match, returning boolean.
These methods only handle one occurrence; use scan for all occurrences.
5. Handling Overlapping Matches
A subtle point is that scan finds non-overlapping matches by default. For example:
"aaaa".scan(/aa/)
# => ["aa", "aa"]
This returns ["aa", "aa"], which is non-overlapping. If you want overlapping matches (like ["aa", "aa", "aa"] for aaa?), you’d need a custom approach, often manually shifting indices in a loop. But for most standard use cases, scan suffices.
6. Example: Extracting Phone Numbers or Emails
text = "Contact me at me@example.com or 555-123-4567"
emails = text.scan(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b/i)
phones = text.scan(/\b\d{3}-\d{3}-\d{4}\b/)
- Each
scanreturns an array of all found emails or phone numbers.
7. Summary
- Use
String#scanto find all matches of a regex in a string, returning an array of match results. - If your regex has capturing groups,
scanreturns an array of arrays (one subarray per group). - You can pass a block to
scanif you want to handle each match as it’s found rather than storing them all. - Single-match methods like
matchor=~only return the first occurrence. - For overlapping matches, you need a more manual approach.
Recommended Courses
Bonus: Strengthen Your Regex & Coding Interview Skills
If you’re honing your Ruby or regex abilities—or preparing for technical interviews—check out the following DesignGurus.io resources:
Grokking the Coding Interview: Patterns for Coding Questions
- Improve your problem-solving approach and gain confidence in interviews.
Grokking System Design Fundamentals
- For higher-level design thinking—useful in many senior engineering interviews.
Looking for personalized feedback? Explore Mock Interviews with ex-FAANG engineers:
Lastly, don’t miss the free tutorials on the DesignGurus.io YouTube channel.
Conclusion: Use String#scan in Ruby to match all occurrences of a regex. For example:
"abc123 def456".scan(/\d+/)
# => ["123", "456"]
This returns an array of all non-overlapping matches found in the string.