How to double single quote (beginner blockage)

Hi!

Sorry for this `stupid´ question but it looks like i am suffering a mental blockage:

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

my `brainless´ attempt was:

[code]
fixed_value = ""
wrong_value.each_with_index do |char, idx|
  fixed_value << char
          if ( (idx < wrong_value.size - 1) && (wrong_value[idx + 1] != '\'') && (idx > 0) && (wrong_value[idx - 1] != '\''))
                  fixed_value << '\''
          end
end
[/code]

but the above results in exactly the same strings. I would appreciate very much your help

./alex

···

--
.w( the_mindstorm )p.

And what if the input string correctly contains double quotes?? :wink:

String doesn't have a each_with_index method.

class String
  def each_with_index
    counter = 0
    each_byte do |char|
      yield char, counter
      counter += 1
    end
  end
end

"abc".each_with_index do |char, index|
  puts char.chr + ' ' + index.to_s
end

Please note that char is an integer, so you have to call char.chr.

Untested, but it should work.

···

--
Posted via http://www.ruby-forum.com/.

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.)

···

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

#: Jules Jacobs changed the world a bit at a time by saying (astral date: 1/18/2006 5:05 PM) :#

And what if the input string correctly contains double quotes?? :wink:

String doesn't have a each_with_index method.

class String
  def each_with_index
    counter = 0
    each_byte do |char|
      yield char, counter
      counter += 1
    end
  end
end

"abc".each_with_index do |char, index|
  puts char.chr + ' ' + index.to_s
end

Please note that char is an integer, so you have to call char.chr.

Untested, but it should work.

I have passed over my no-brainer moment:

[code]
fixed_value = ""
idx = 0
while (idx < wrong_value.size) do
  fixed_value << wrong_value[idx]
  if ( wrong_value[idx] == 39 )
    if ( (wrong_value[idx + 1] != 39) )
      if ( idx > 0 && wrong_value[idx - 1] != 39 )
        fixed_value << '\''
      end
    end
         end
         idx += 1
end
[/code]

but now i've reached the no-ruby point. Can you teach me what would be the ruby way?

Note: the double quotes are not considered in this problem; in fact i am removing them right from the beginning

./alex

···

--
.w( the_mindstorm )p.

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

···

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.)

--
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

#: Gavin Kistner changed the world a bit at a time by saying (astral date: 1/18/2006 5:28 PM) :#

···

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.)

I've been fighting to figure out how a regexp should look, so I appreciate very much your approach. I will be reading it carefully.

thanks,

./alex
--
.w( the_mindstorm )p.

#: Gavin Kistner changed the world a bit at a time by saying (astral date: 1/18/2006 5:28 PM) :#

···

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.)

I've been fighting to figure out how a regexp should look (mainly the first/last position part), so I appreciate very much your approach. I will be reading it carefully.

... and what is Oniguruma? (sounds pretty cool :slight_smile: ).

thanks,

./alex
--
.w( the_mindstorm )p.

The new Regex library for Ruby 2.0?

Jules

···

--
Posted via http://www.ruby-forum.com/.