Today I Learned

hashrocket A Hashrocket project

Case Regex Matching with Capture Groups

I ran into a problem where I wanted to use a case statement to match against a regex, but also capture some values from the matched data.

Say I want to match on a pair of numbers wrapped in parens like (2,4) and add them together. If I match without capture groups I have to grab the numbers again in the when block:

x = "(2,4)"
case x
when /\(\d+,\d+\)/
  a,b = x.scan(/\d+/)
  a.to_i + b.to_i
end
# => 6

Seems a shame to have perform another op to get a and b. What if we used capturing groups like /\((\d+),\(d+)\)/? How do we refer to those captured values inside the when? We can use some of ruby's special variables, namely $1 and $2 to refer to the captured groups of the last regexp.

x = "(2,4)"
case x
when /\((\d+),(\d+)\)/
  $1.to_i + $2.to_i
end
# => 6

$1 and $2 feel a little magic, so we can name our capture groups group1 and group2, and access those from $~ (the MatchData of the last regexp).

x = "(2,4)"
case x
when /\((?<group1>\d+),(?<group2>\d+)\)/
  $~[:group1].to_i + $~[:group2].to_i
end
# => 6
See More #ruby TILs
Looking for help? Each developer at Hashrocket has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, have written some of the most popular gems, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.