Robert Klemme
7/20/2007 6:18:00 AM
2007/7/20, Kyle Schmitt <kyleaschmitt@gmail.com>:
> 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]/, '<\\&>'
=> "<c>am<e>l_<c>as<e>"
irb(main):011:0> "camel_case".gsub /c(.)/, '<\\1>'
=> "<a>mel_<a>se"
Regards
robert