Splatting Regex Matches
When extracting data from strings using regular expressions, Ruby’s splat
operator, *
, can come in handy.
To show how, let’s parse the string 'ios;version=7.0.4'
into two variables:
one containing the substring 'ios'
and one containing '7.0.4'
.
This is one way of doing it:
REGEX = /^(.*);version=(.*)$/
string = 'ios;version=7.0.4'
matches = string.match(REGEX)
os = matches[1]
version = matches[2]
os #=> "ios"
version #=> "7.0.4"
Another way of accomplishing the same thing is to use the *
operator to splat
out the returned matches.
REGEX = /^(.*);version=(.*)$/
string = 'ios;version=7.0.4'
_, os, version = *string.match(REGEX)
os #=> "ios"
version #=> "7.0.4"
Let’s take a look at how this works behind the scenes.
In the example above, the string stored in the string
variable matches the
REGEX
causing String#match
to return a MatchData
object.
matches = string.match(REGEX)
matches #=> #<MatchData "ios;version=7.0.4" 1:"ios" 2:"7.0.4">
The MatchData
object is then supplied as an argument to the splat operator.
The splat operator calls the MatchData#to_a
method to get an array
representation of the matches.
matches.to_a #=> ["ios;version=7.0.4", "ios", "7.0.4"]
After getting the array, the splat operator explodes it and assigns each of its elements to the corresponding variable on the left side of the assignment.
_, os, version = *['ios;version=7.0.4', 'ios', '7.0.4']
_ #=> "ios;version=7.0.4"
os #=> "ios"
version #=> "7.0.4"
Using _
as a variable name might seem strange but it’s completely valid to do
so in Ruby. It’s also an idiomatic way of signaling to the reader that the
variable’s value isn’t used.
We can use the fact that the splat operator calls to_a
on its argument in our
own classes like this:
class SplatMe
def to_a
[1, 2, 3]
end
end
splat_me = SplatMe.new
puts *splat_me
#=> 1
#=> 2
#=> 3
But what happens when the string in the example above doesn’t match the
REGEX
?
REGEX = /^(.*);version=(.*)$/
string = "does not match"
_, os, version = *string.match(REGEX)
os #=> nil
version #=> nil
If the string doesn’t match, match
returns nil
, the splat operator calls
NilClass#to_a
which always returns an empty array. Splatting an empty array
over multiple variables assigns nil
to all of them:
a, b, c = *[]
a #=> nil
b #=> nil
c #=> nil