"Mike Stok" <mike / stok.co.uk> schrieb im Newsbeitrag
news:MWOPb.54576$lGr.29805 / twister01.bloor.is.net.cable.rogers.com...
> In article <buo0rc$j5ef5$1 / ID-52924.news.uni-berlin.de>,
> Robert Klemme <bob.news / gmx.net> wrote:
> >
> >"Mark J. Reed" <markjreed / mail.com> schrieb im Newsbeitrag
> >news:20040121221951.GD16733 / mulan.thereeds.org...
> >> On Thu, Jan 22, 2004 at 06:57:22AM +0900, Ralph Mason wrote:
> >> > What am I missing here.  I am trying to replace a single quote with
> >the
> >> > string \'
> >>
> >> You're missing an extra level of processing applied to the
replacement
> >> string for gsub in order to let you include parts of what you're
> >> replacing.
> >
> >No, in this case he's missing extra backslashes:
> >
> >irb(main):002:0> str='a\'o'
> >=> "a'o"
> >irb(main):003:0> str.gsub(/'/, '\\\\\'' )
> >=> "a\\'o"
> >irb(main):004:0> puts str.gsub(/'/, '\\\\\'' )
> >a\'o
> >=> nil
> >
> >It does look a bit odd, but the explanation is logical: There are two
> >levels of escaping involved.  The first level is that needed for the
ruby
> >parser to get the expected characters into the replacement string.  The
> >second level is used in order to be able to use a backslash literally
in
> >the substitution string.
> >
> >irb(main):005:0> puts '\\\\\''
> >\\'
> >=> nil
> >
> >You need two backslashes in the substitution string to prevent gsub
from
> >interpreting the backslash as escape char.  That makes four backslashes
> >when entering the string.  The fifth backslash escapes the single quote
in
> >order to be able to include it into the string.
>
> You can make life a little easier by picking a quote other than ' to
> get rid of one backslash e.g.

Yes, although it's just a small improvement.

> [mike@ratdog mike]$ irb --simple-prompt
> >> str = "a'o"
> => "a'o"
> >> puts str.gsub(/'/, "\\\\'")
> a\'o
> => nil
>
> It can be tiresome to remember how many times a string will be scanned
> in a context where \ characters matter, so I prefer using the block form
> e.g.
>
> >> puts str.gsub(/(')/) { |c| "\\#{c}" }
> a\'o
> => nil
>
> ...but I have never measured whether this is significantly more
> expensive.

It's definitely more expensive, which is not really a surprise given the
additional overhead of

 - a block yield
 - string replacement with {}

But even with a constant string there's still the block call overhead:

14:21:43 [ADMIN]: /c/temp/ruby/rx-replace-bm.rb
                user     system      total        real
direct      0.766000   0.000000   0.766000 (  0.763000)
direct &    0.766000   0.000000   0.766000 (  0.769000)
block       1.765000   0.000000   1.765000 (  1.770000)
block fix   1.438000   0.000000   1.438000 (  1.432000)
14:21:50 [ADMIN]: cat /c/temp/ruby/rx-replace-bm.rb
#!/usr/bin/ruby

require 'benchmark'
include Benchmark

N=100000

str = '  /* comment */  String s = "***/";  '

bm(10) do |x|
  x.report("direct") do
    for n in 1..N
      str.gsub( /"/, '\\\\"' )
    end
  end

  x.report("direct &") do
    for n in 1..N
      str.gsub( /"/, '\\\\\\&' )
    end
  end

  x.report("block") do
    for n in 1..N
      str.gsub( /"/ ) {|m| "\\#{m}"}
    end
  end

  x.report("block fix") do
    for n in 1..N
      str.gsub( /"/ ) {|m| '\\"'}
    end
  end
end
14:21:58 [ADMIN]:

> Hal, is this a FAQ?  "How do I replace ' with \' in a string?"  I'm sure
> that this has come up a few times...

I put it on the Wiki:
http://www.rubygarden.org/ruby?RegexpCookbook

Cheers

    robert