From: Robert Klemme Date: 2009-05-11T21:47:49+09:00 Subject: Re: gsub pattern substitution and ${...} 2009/5/11 Sarah Allen : > Robert Klemme wrote: >> even with proper escaping this won't work as the string interpolation >> takes place *before* gsub is invoked and hence URI.escape will insert >> something but not the matched portion.  In your tests it has probably >> worked because $2 was properly set from the previous match. > > really? so the ${...} gets evaluated before the param is passed to gsub, All method parameters are evaluated before method invocation - this is true for every method invocation in Ruby. > but the block is passed as code, so then it is evaluated after. In the case of gsub the block is invoked once for each match. > Using the previous attempt, with a fresh irb session, I can see the > issue: >>> $1 > => nil >>> $2 > => nil >>> $3 > => nil >>> require 'URI' > => true >>> s.gsub(/href=(['"])([^']*)/, "href=\\1#{URI.escape($2)}\\3") > NoMethodError: private method `gsub' called for nil:NilClass >  from > /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/uri/common.rb:289:in > `escape' >  from (irb):8 > >>> $1 > => nil >>> $2 > => nil >>> $3 > => nil >>> s = "" > => "" >>> require 'URI' > => true >>> s.gsub(/href=(["'])([^'"]+)\1/) { > ?> "href=#$1#{URI.escape($2)}#$1" } > => "" > > Nice! :-) >> Note that my regexp has another weakness: the quote character not used >> to quote the URI should be allowed as part of the URI.  I did not want >> to complicate things too much but if you want to deal with this the >> regular expression must be made a bit more complex. > > Wow, interesting. That would be incorrect HTML that the browser doesn't > deal with well, so I'll not worry about it for this case, but I would be > curious how it might be handled. Basically you need an alternative and more capturing groups along the lines of '([^']+)'|"([^"]+)" > Thanks so much, You're welcome. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/