codigomonstruo
codigomonstruo

Reputation: 1091

How do I replace all the apostrophes that come right before or right after a comma?

I have a string aString = "old_tag1,old_tag2,'new_tag1','new_tag2'" I want to replace the apostrophees that come right before or right after a comma. For example in my case the apostrophees enclosing new_tag1 and new_tag2 should be removed. This is what I have right now

aString = aString.gsub("'", "")

This is however problematic as it removes any apostrophe inside for example if I had 'my_tag's' instead of 'new_tag1'. How do I get rid of only the apostrophes that come before or after the commas ?

My desired output is

aString = "old_tag1,old_tag2,new_tag1,new_tag2"

Upvotes: 1

Views: 173

Answers (3)

Zack
Zack

Reputation: 1231

Non regex replacement

Regular expressions can get really ugly. There is a simple way to do it with just string replacement: search for the pattern ,' and ', and replace with ,

aString.gsub(",'", ",").gsub("',", ",")
=> "old_tag1,old_tag2,new_tag1,new_tag2'"

This leaves the trailing ', but that is easy to remove with .chomp("'"). A leading ' can be removed with a simple regex .gsub(/^'/, "")

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110725

This answers the question, "I want to replace the apostrophes that come right before or right after a comma".

r = /
    (?<=,) # match a comma in a positive lookbehind
    \'     # match an apostrophe
    |      # or
    \'     # match an apostrophe
    (?=,)  # match a comma in a positive lookahead
    /x     # free-spacing regex definition mode        

aString = "old_tag1,x'old_tag2'x,x'old_tag3','new_tag1','new_tag2'"

aString.gsub(r, '')
  #=> => "old_tag1,x'old_tag2'x,x'old_tag3,new_tag1,new_tag2'"

If the objective is instead to remove single quotes enclosing a substring when the left quote is at the the beginning of the string or is immediately preceded by a comma and the right quote is at the end of the string or is immediately followed by comma, several approaches are possible. One is to use a single, modified regex, as @Dimitry has done. Another is to split the string on commas, process each string in the resulting array and them join the modified substrings, separated by commas.

r = /
    \A     # match beginning of string
    \'     # match single quote
    .*     # match zero or more characters
    \'     # match single quote
    \z     # match end of string
    /x     # free-spacing regex definition mode

aString.split(',').map { |s| (s =~ r) ? s[1..-2] : s }.join(',')
  #=> "old_tag1,x'old_tag2'x,x'old_tag3',new_tag1,new_tag2"

Note:

arr = aString.split(',')
  #=> ["old_tag1", "x'old_tag2'x", "x'old_tag3'", "'new_tag1'", "'new_tag2'"]
"old_tag1"     =~ r #=> nil
"x'old_tag2'x" =~ r #=> nil
"x'old_tag3'"  =~ r #=> nil
"'new_tag1'"   =~ r #=> 0
"'new_tag2'"   =~ r #=> 0

Upvotes: 0

Tim Tonkonogov
Tim Tonkonogov

Reputation: 1117

My guess is to use regex as well, but in a slightly other way:

aString = "old_tag1,old_tag2,'new_tag1','new_tag2','new_tag3','new_tag4's'"
aString.gsub /(?<=^|,)'(.*?)'(?=,|$)/, '\1\2\3'
#=> "old_tag1,old_tag2,new_tag1,new_tag2,new_tag3,new_tag4's"

The idea is to find a substring with bounding apostrophes and paste it back without it.

regex = /
  (?<=^|,) # watch for start of the line or comma before
  '        # find an apostrophe
  (.*?)    # get everything between apostrophes in a non-greedy way
  '        # find a closing apostrophe
  (?=,|$)  # watch after for the comma or the end of the string
/x

The replacement part just paste back the content of the first, second, and third groups (everything between parenthesis).

Thanks for @Cary for /x modificator for regexes, I didn't know about it! Extremely useful for explanation.

Upvotes: 1

Related Questions