Ruby Globals that are not Global
Ruby's regular expression class sets some $
prefixed variables, but they're not global.
Everytime you perform a Regexp
match, including using the match operator =~
, the following variables are populated:
$~
is equivalent toRegexp.last_match
;$&
contains the complete matched text;$`
contains string before match;$'
contains string after match;$1
,$2
and so on contain text matching first, second, etc capture group;$+
contains last capture group.
While I try and avoid arcane incantations, preferring to use a MatchData
object where possible, there are genuinely useful in dealing with case
statements and regular expression matching.
my_string = 'The HMS Bellerophon is a fine ship'
case my_string
when /(HMS [A-z]+)/
puts "Ahoy there, #{$1}"
when /(USS [A-z]+/
puts "Greetings, #{$1}"
end
The regex $-
variables give me access to the result of the match in the body of the branch after the matching has taken place; very useful when you don't have a MatchData
to work with.
The documentation describes these variables in a misleading way, in my opinion...
Pattern matching sets some global variables
The regex special variables are not global – they are method-local and thread-local. If you try and use them outside of the method that you performed the match, they will be nil. This is important if you delegate your matching elsewhere:
my_string = 'The HMS Bellerophon is a fine ship'
# does not work
# $1 will be local to the lambdas
case my_string
when his_majestys_navy
puts "Ahoy there, #{$1}"
when united_states_navy
puts "Greetings, #{$1}"
end
def his_majestys_navy
-> (name) { /(HMS [A-z]+)/ }
end
def united_states_navy
-> (name) { /(USS [A-z]+/ }
end
# does work
case my_string
when his_majestys_navy
puts "Ahoy there, #{$1}"
when united_states_navy
puts "Greetings, #{$1}"
end
def his_majestys_navy
/(HMS [A-z]+)/
end
def united_states_navy
/(USS [A-z]+/
end
Member discussion