tags:

views:

40

answers:

1

First, a working example:

string = "foo-bar-25-baz"
if string =~ /(.+)-(10|25)(?:-(baz))?/
  puts $1 
  puts $2
  puts $3
end

This produces 'foo-bar', '25' and 'baz' on three lines, as expected. But if we do this:

string = "foo-bar-25-baz"
if string =~ /(.+)-(10|25)(?:-(baz))?/
  puts $1.gsub('-', ' ') # Here be the problem
  puts $2 # nil
  puts $3 # nil
end

the values of $2 and $3 are now nil. I have to puts $2 and puts $3 and then $1.gsub(...), and it will work. As far as I can tell this only applies to gsub and gsub!

This causes the same problem:

string = "foo-bar-25-baz"
if string =~ /(.+)-(10|25)(?:-(baz))?/
  puts $3.gsub('hard', 'h')
  puts $1 # nil
  puts $2 # nil
end

I spent about 15 minutes debugging this and I'm wondering why.

+5  A: 

gsub is most likely re-assigning those variables (as would pretty much any other function that uses the regexp engine). If you need to call gsub before using all your original match results, store them to a local variable first with something like match_results = [$1, $2, $3].

bta
+1, gsub uses a regular expression to find the string to replacae, and so the special variables `$1`, `$2`, etc. will be reassigned!
jigfox
Since variables with names starting with a `$` are globals, you never know what else might be able to change their values.
bta
You're exactly right, it's re-assigning the global variables, which makes sense. Thanks!
rspeicher