Reputation: 1433
In order to save regex capture groups to a local variable, the regex must be on the left side of an operation such as /(?<somegroup>someregex)/ =~ 'somestring'
. For example, given a url string, extracting the top level domain:
/(?<extract>\b.com\b)[\/]{0,1}/ =~ 'google.com'
puts extract # => .com
There are various domains (.org, .scb, .wine, .me, etc). My strategy is to store all possible tlds from a reputable source in an array, and iterate through each one and pass it to the regex. How do you pass a variable to the literal?
Here is a simplified method of what I am trying to do:
def example_extract(url_str)
exmpl = '.com'
regx = /(?<extract>\b#{exmpl}\b)[\/]{0,1}/
regx =~ url_str
extract
end
example_extract('google.com')
# => NameError: undefined local variable or method `extract' for main:Object
I fail to pass a variable to a left hand (literal) regex operation. Why is my capture group extract
not defined?
Upvotes: 1
Views: 98
Reputation: 1433
For anyone's future reference. You have to use regexp's MatchData
. This is what worked for me:
def example_extract(url_str)
exmpl = '.com'
regx = /(?<extract>\b#{exmpl}\b)[\/]{0,1}/
extract = regx.match(url_str)[:extract]
p extract
end
example_extract('google.com')
Upvotes: 0
Reputation: 168071
Under the documentation for Regexp#=~, it says:
This assignment is implemented in the Ruby parser. The parser detects ‘regexp-literal =~ expression’ for the assignment. The regexp must be a literal without interpolation and placed at left hand side.
The reason local variable was not assigned is because your regex was defined using interpolation, and is not a literal.
As the citation implies, assigning a local variable is done during parsing phase, and since string interpolation is done during run time, there seems no way to detour the limitation imposed by the specification.
Upvotes: 1