Robert Klemme
1/18/2006 4:31:00 PM
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.)
No lookbehinds / -aheads needed, or am I missing something? As far as I
can see special treatment of quotes at beginning and end of string was not
a requirement.
>> "al'alamein".gsub(/''?/, '\'\'')
=> "al''alamein"
>> "'Hey, it's al'alamein'".gsub(/''?/, '\'\'')
=> "''Hey, it''s al''alamein''"
>> "'''Jimbo' said, 'this isn''t too hard'.''".gsub(/''?/, '\'\'')
=> "''''Jimbo'' said, ''this isn''t too hard''.''"
Can't see any difference to your output - but the RX is much simpler. :-)
Cheers
robert