Finding a pattern, not an exact string
"Does this look like an email?" is a different question from "is this that string?"
input = "[email protected]"
input == "[email protected]" # true, but only for this one exact address
That comparison answers a question about one specific string. A signup form doesn't know the visitor's email address in advance. It needs to check "does this look like an email": a shape, not an exact value. == can't express "some characters, then an @, then more characters, then a dot, then a few letters". A regular expression (regex, for short) can.
A regex literal, written in Ruby
pattern = /gmail/
pattern.class
# Regexp
/gmail/ is a Regexp object, a Ruby object like any other, created with slash delimiters instead of Regexp.new. The simplest regex is plain text. /gmail/ matches any string that contains the characters g, m, a, i, l in that order, anywhere inside it.
=~: the first way to run one
"[email protected]" =~ /gmail/
# 4, the index where the match starts
"[email protected]" =~ /gmail/
# nil, no match anywhere in the string
=~ runs the regex against a string and returns the index where the first match starts, or nil if nothing matches. nil is falsy and every integer (including 0) is truthy, so =~ fits straight into an if:
email = "[email protected]"
if email =~ /gmail/
puts "looks like a Gmail address"
end
# "looks like a Gmail address"
Watch one sharp edge. A match at index 0 is still a match, and 0 is truthy in Ruby (only nil and false are falsy), so this pattern is safe. It would break for a method that returned false on no match instead of nil. That's why =~'s "index or nil" contract matters.
Not every character means itself
., *, +, ?, [, ], (, ), {, }, |, \, ^ and $ all have special meanings inside a regex. This course spends time on several of them from lesson 5. For now: to match one of these characters as plain text, escape it with a backslash:
"3.14" =~ /3.14/ # 0, but "." here means "any character", so this also matches "3x14"
"3x14" =~ /3.14/ # 0, matched anyway, probably not what was intended
"3.14" =~ /3\.14/ # 0, "\." means a literal dot, and only a literal dot
"3x14" =~ /3\.14/ # nil, correctly rejected
Where this goes
This course builds the toolkit behind that email check. It covers pulling structured pieces out of a match, finding every occurrence instead of the first, and the anchors and character classes that keep a pattern from being too loose. Search-and-replace comes after that. The last lesson uses all of it to read a regular expression that runs in this app's models.
Key takeaways
==checks for one exact string; a regex checks for a shape that many different strings can share./pattern/is aRegexpobject;=~runs it against a string and returns the index of the first match, ornilif there's no match.0is a valid, truthy match index in Ruby, soif str =~ /pattern/treats "matched at the start" as a match.- Characters like
.,*,+and?are special inside a regex; to match one as plain text, escape it:\.instead of..
Keep going with lesson 2
MatchData or a plain Yes/No: match vs match?
Compares match, which returns MatchData, with match?, which returns a boolean and leaves $~ untouched.
A free account also gives you the quizzes, your progress and notes, and the discussion.