Splatting Regex Matches
When extracting data from strings using regular expressions, Ruby’s splat
*, 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
This is one way of doing it:
REGEX = /^(.*);version=(.*)$/ string = 'ios;version=7.0.4' matches = string.match(REGEX) os = matches version = matches 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.
matches = string.match(REGEX) matches #=> #<MatchData "ios;version=7.0.4" 1:"ios" 2:"7.0.4">
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"
_ 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 = /^(.*);version=(.*)$/ string = "does not match" _, os, version = *string.match(REGEX) os #=> nil version #=> nil
If the string doesn’t match,
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