Heading image for post: Using Match vs. =~ in Ruby

Ruby

Using Match vs. =~ in Ruby

Profile picture of Craig Hafer

Today I wanted to go over the Match methods and the =~ in Ruby. I want to cover some of the differences between them, and some nice side effects you can take advantage of.

Let’s look at some simple use cases, and see what we find:

# Simple regex that looks for "www.*.com"
regex = /www\..*\.com/ 

# Generic string website we will be matching against
website = "https://www.example.com/something" 

regex.match(website)
=> #<MatchData "www.example.com">

website.match(regex)
=> #<MatchData "www.example.com">

regex.match("invalid")
=> nil

So, looking at this, we can see that a MatchData object is returned, unless there is no match then nil is returned.

Now, let’s say we captured this MatchData object into a variable. What are some things we can do with it? Well, I’m glad you asked. Here are a few methods you might find useful:

match = regex.match(website)

# Returns everything before the match
match.pre_match
=> "https://"

# Returns what was matched
match.to_s
=> "www.example.com"

# Also returns what was matched
match[0]
=> "www.example.com"

# Returns everything after the match
match.post_match
=> "/something"

# Returns the regex used to match
match.regexp
=> /www\..*\.com/

Now, let’s change the regex to capture the domain.

regex = /www\.(.*)\.com/

match = regex.match(website)
=> #<MatchData "www.example.com" 1:"example">

# Returns an array of all the items captures. In our case, it’s just one,
match.captures
=> ["example"]

So, if you need to work on the data after the match, this is definitely the way to go. As you have access to a lot of useful information inside of the MatchData object. However, if you just need to check if a string matches the regex, and that’s it, you might want to consider using the "bacon cannon" (=~).

Try and convince me that’s not bacon being shot out of a cannon

The main difference between the "bacon cannon" and #match are that =~ returns the index of the match instead of a MatchData object, but it also returns nil if there is no match.

We can perform some logic if the string matches a bit cleaner this way.

"Success!" if regex =~ website
=> "Success!"

"Success!" if regex =~ "invalid"
=> nil

Also, if you did need to perform some work on the data, but still wanted to use the "bacon cannon", you might be able to use these Special Global Variables to get away with it:

regex =~ website
=> 8

$` # Equivalent to match.pre_match
=> "https://"

$& # Equivalent to match.to_s or match[0]
=> "www.example.com"

$’ # Equivalent to match.post_match
=> "/something"

$1 # Equivalent to match[1]
=> "example"

$2 # Equivalent to match[2]
=> nil

I hope this was able to help you learn about some of the subtle differences between Match and =~.
Even if you knew all of this, I consider it a win if more people call =~ the bacon cannon.


Photo by: Erik Mclean

More posts about Ruby