On Nov 3, 2004, at 12:12 PM, Paul Rubel wrote:

> Hi,
>
> I'm trying to take a string and escape a single quote if it is not
> already escaped. My first thought was to look at the string and if I
> see a quote without a backslash before it put the backslash there.

What about:

gsub(/(\\*)'/) { |m| $1.length % 2 == 0 ? $1 + "\\'" : m }

> Would look-behind be an option here out of the box?

Surprisingly, I don't believe Ruby yet supports lookbehind.

> While I was experimenting I saw some behavior I don't understand and
> am hoping someone can explain it to me:
>
> prubel@cornet /tmp> cat /tmp/t.rb ; ruby /tmp/t.rb
> 2.times do
>   # replace not a slash followed by a quote with not a slash
>   # and an escaped quote.
>   puts("\\'Summer's Day".gsub(/([^\\\\])'/,"*#{$1}\\\\'*"))

The above line is problematic for two reasons.  First, when using the 
replacement string version of gsub(), your string is interpolated 
before the method is even called let alone before any matches are made 
so $1 and friends are not set.  Instead, try using a \1 in a single 
quoted string or \\1 in a double to get the value you're after.

Two, I don't understand your pattern.  [^\\\\] means ONE character that 
is not a slash and also not a slash.  It's identical to [^\\].  I think 
you meant to say, not two slashes, but that's a little harder to 
express in a regex.  And what if there are three slashes?  See my 
solution above for a different approach.

>   puts $1
> end
> #end
> \'Summe*\'*s Day
> r
> \'Summe*r\'*s Day
> r
> prubel /tmp> ruby --version
> ruby 1.8.1 (2004-02-06) [i686-linux-gnu]
>
>
> I'm confused at to why the output is different for the two
> iterations? Why doesn't the r get placed in the first output?

Because $1 isn't set in time for the first replacement, but it is set 
when the second string is built (set by the first match).

Hope that helps.

James Edward Gray II