From: Robert Klemme Date: 2007-07-20T15:17:30+09:00 Subject: Re: regex backreference weirdness... 2007/7/20, Kyle Schmitt : > It all started with trying to convert some strings with underscores in > them, to camel case...and me thinking of regexes as sed regexes > > It looks like gsub saves back references, but only after the whole > method exits, so it can't use what it found. Is this right? > > Below is what I tried, which leads me up to the question of... what > would the _right_ way be of doing this? > > irb>"camel_case".gsub(/_(.)/,$1.upcase) You need to be aware that $1.upcase is evaluated *before* the method call. So it can *never* be able to do calculations based on match state. You rather want to use the block for, where the block is invoked once per match. For example, you can do irb(main):005:0> "camel_case".gsub(/(?:\A|_)(.)/) {|m| $1.capitalize } => "CamelCase" > NoMethodError: undefined method `upcase' for nil:NilClass > from (irb):1 > #Which made me say Hu? it looks like a valid back reference to me... No, with the non block form you need to use \1, \2 etc. as has been mentioned already. > #So I tried > "camel_case"=~/_(.)/ > irb>puts $1 > =>"c" > #ok really wierd... > irb>"camel_case".gsub(/_(.)/,$1.upcase) > =>"camelCase" > #Right, I'll buy that since $1 is still hanging around > irb>"camel_face".gsub(/_(.)/,$1.upcase) > =>"camelCase" > irb>"camel_face".gsub(/_(.)/,$1.upcase) > =>"camelFase" > #Ha ha! gsub DOES save a backreference... so why isn't this working?! :( You're still working on the value of $1 from the last invocation. Proper backreferencing in the non block form looks like this: irb(main):010:0> "camel_case".gsub /[cde]/, '<\\&>' => "aml_as" irb(main):011:0> "camel_case".gsub /c(.)/, '<\\1>' => "mel_se" Regards robert