Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does capturing named groups in Ruby result in "undefined local variable or method" errors?

I am having trouble with named captures in regular expressions in Ruby 2.0. I have a string variable and an interpolated regular expression:

str = "hello world"
re = /\w+/
/(?<greeting>#{re})/ =~ str
greeting

It raises the following exception:

prova.rb:4:in <main>': undefined local variable or methodgreeting' for main:Object (NameError)
shell returned 1

However, the interpolated expression works without named captures. For example:

/(#{re})/ =~ str
$1
# => "hello"
like image 850
giuseta Avatar asked Jan 13 '23 17:01

giuseta


2 Answers

Named Captures Must Use Literals

You are encountering some limitations of Ruby's regular expression library. The Regexp#=~ method limits named captures as follows:

  • The assignment does not occur if the regexp is not a literal.
  • A regexp interpolation, #{}, also disables the assignment.
  • The assignment does not occur if the regexp is placed on the right hand side.

You'll need to decide whether you want named captures or interpolation in your regular expressions. You currently cannot have both.

like image 132
Todd A. Jacobs Avatar answered Jan 20 '23 22:01

Todd A. Jacobs


Assign the result of #match; this will be accessible as a hash that allows you to look up your named capture groups:

> matches = "hello world".match(/(?<greeting>\w+)/)
=> #<MatchData "hello" greeting:"hello">
> matches[:greeting]
=> "hello"

Alternately, give #match a block, which will receive the match results:

> "hello world".match(/(?<greeting>\w+)/) {|matches| matches[:greeting] }
=> "hello"
like image 39
Chris Heald Avatar answered Jan 21 '23 00:01

Chris Heald