Regular Expressions
Prerequisites: String methods
A regular expression (regex) is a pattern for matching text: "a
digit", "an email-looking thing", "a word at the start of a line". In
Ruby, regexes are written between slashes: /pattern/.
Building blocks
| Pattern | Matches |
|---|---|
\d |
a digit |
\w |
a letter, digit, or underscore |
\s |
whitespace |
. |
any character except a newline |
[aeiou] |
any one of these characters |
+ / * |
one or more / zero or more of the previous |
? |
optional |
{3} |
exactly 3 of the previous |
\A \z |
start / end of the whole string |
( ) |
a capture group |
Example
text = "Order #1042 shipped on 2025-01-15 to ada@example.com"
p text.match?(/\d{4}-\d{2}-\d{2}/)
p text[/#(\d+)/, 1]
p text.scan(/\d+/)
if (m = text.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/))
puts "Year #{m[:year]}, month #{m[:month]}"
end
p text.gsub(/\d/, "#")
p "a1b22c333".split(/\d+/)
Expected output
true
"1042"
["1042", "2025", "01", "15"]
Year 2025, month 01
"Order ##### shipped on ####-##-## to ada@example.com"
["a", "b", "c"]
match?returns true/false — the fastest check.text[regex, 1]returns the first capture group.scanreturns every match.(?<name>...)is a named capture group.=~andcase/whenalso accept regexes.
Validating input: anchor the pattern
ZIP = /\A\d{5}\z/
p "12345".match?(ZIP)
p "12345x".match?(ZIP)
p "ab\n12345".match?(/^\d{5}$/)
true
false
true
In Ruby, ^ and $ mean start and end of a line, not of the whole
string — so the last line matches even though the string isn't a ZIP
code. For validation, always use \A and \z.
Try patterns interactively in the Regex Tester before putting them in code.
Common mistakes
- Using
^...$to validate input — a classic security bug in Ruby apps. Use\A...\z. - Trying to validate emails completely with a regex. A simple "something@something.something" check plus sending a confirmation email is more reliable.
Practice
Extract every hashtag (words starting with #) from
"Loving #ruby and #rails today #dev".
Show solution
p "Loving #ruby and #rails today #dev".scan(/#\w+/)
["#ruby", "#rails", "#dev"]