On Thu, 19 Jan 2006, Gavin Kistner wrote:

> On Jan 18, 2006, at 7:47 AM, Alexandru Popescu wrote:
>> if I have a string that contains single quote (f.e. "al'alamein") i would 
>> like to escape it with another single quote (=> "al''alamein").
>> 
>> there are cases when these strings are already escaped according to the 
>> above rule, so those should remain untouched
>
> Let's build this step by step.
>
> The simple case is pretty simple, using Regular Expressions. You want to find 
> a single quote that has characters other than a single quote on either side, 
> and replace it with two single quotes:
>
> irb(main):001:0> input = "al'alamein"
> => "al'alamein"
> irb(main):002:0> input.gsub( /([^'])'([^'])/, "\\1''\\2" )
> => "al''alamein"
>
> The above breaks if the single quote occurs at the beginning or end of the 
> input:
> irb(main):003:0> input2 = "'Hey, it's al'alamein'"
> => "'Hey, it's al'alamein'"
> irb(main):004:0> input2.gsub( /([^'])'([^'])/, "\\1''\\2" )
> => "'Hey, it''s al''alamein'"
>
> ...so let's say that there has to be a non-single quote at either end, OR the 
> start/end of the string:
> irb(main):005:0> input2.gsub( /(\A|[^'])'([^']|\Z)/, "\\1''\\2" )
> => "''Hey, it''s al''alamein''"
>
> Finally, the above handles 1 or 2 single quotes in a row correctly, but not 3 
> or more. Probably you want to ensure that single quotes always come in 
> even-numbered runs.
>
> Instead of looking for a single quote in the middle of that regular 
> expression, we'll look for a single quote followed by an even number of 
> single quotes. Then we'll add one more.
>
> irb(main):006:0> input3 = "'''Jimbo' said, 'this isn''t too hard'.''"
> => "'''Jimbo' said, 'this isn''t too hard'.''"
> irb(main):007:0> input3.gsub( /(\A|[^'])'('')*([^']|\Z)/, "\\1''\\2\\3" )
> => "''''Jimbo'' said, ''this isn''t too hard''.''"
>
>
> (The above could be made a bit simpler with lookaheads and lookbehinds. I've 
> chosen not to use them because you need Oniguruma to do lookbehinds, and no 
> sense cluttering the example with one technique for the front and another for 
> the back.)

nice explanation gavin.  my brain is too feeble for that but i do the same
thing logically using

   irb(main):016:0> %Q( '''Jimbo' said, 'this isn''t too hard'.'' ).gsub(/'+/){|m| m.size % 2 == 0 ? m : m << "'"}
   => " ''''Jimbo'' said, ''this isn''t too hard''.'' "

i assume it would be slower though.

cheers.

-a
-- 
strong and healthy, who thinks of sickness until it strikes like lightning?
preoccupied with the world, who thinks of death, until it arrives like
thunder?  -- milarepa