Ruby replace double blackslash with single blackslash - ruby

In Ruby I am trying to replace double backslash \\ with single backslash \ in string but it's not working.
This is my string
line = "this\\is\\line"
desired output
"this\is\line'
This is what i tried
line.gsub("\\", "\") # didn't work
line.gsub("\\", "/\") # didn't work
line.gsub("\\", '\') # didn't work with single quote as well
line.gsub("\\", '/\') # din't work with single quote as well

You are being tricked - it actually is working, but the console is displaying it escaped with \ in line. Use puts to actually see what it is being set without it being escaped with backslashes.
So #1: line = "this\\is\\line" is actually this\is\line. Proof:
irb(main):015:0> line = "this\\is\\line"
=> "this\\is\\line"
irb(main):016:0> puts line
this\is\line
So to actually make a string with double backslashes, you need: line = "this\\\\is\\\\line". Proof:
irb(main):017:0> line = "this\\\\is\\\\line"
=> "this\\\\is\\\\line"
irb(main):018:0> puts line
this\\is\\line
So finally, once you actually have a string with double backslashes, this is the gsub you want: line.gsub("\\\\", "\\")
irb(main):020:0> line = "this\\\\is\\\\line"
=> "this\\\\is\\\\line"
irb(main):021:0> puts line.gsub("\\\\", "\\")
this\is\line

Related

ruby - weird duplication with backtick in gsub [duplicate]

s = "#main= 'quotes'
s.gsub "'", "\\'" # => "#main= quotes'quotes"
This seems to be wrong, I expect to get "#main= \\'quotes\\'"
when I don't use escape char, then it works as expected.
s.gsub "'", "*" # => "#main= *quotes*"
So there must be something to do with escaping.
Using ruby 1.9.2p290
I need to replace single quotes with back-slash and a quote.
Even more inconsistencies:
"\\'".length # => 2
"\\*".length # => 2
# As expected
"'".gsub("'", "\\*").length # => 2
"'a'".gsub("'", "\\*") # => "\\*a\\*" (length==5)
# WTF next:
"'".gsub("'", "\\'").length # => 0
# Doubling the content?
"'a'".gsub("'", "\\'") # => "a'a" (length==3)
What is going on here?
You're getting tripped up by the specialness of \' inside a regular expression replacement string:
\0, \1, \2, ... \9, \&, \`, \', \+
Substitutes the value matched by the nth grouped subexpression, or by the entire match, pre- or postmatch, or the highest group.
So when you say "\\'", the double \\ becomes just a single backslash and the result is \' but that means "The string to the right of the last successful match." If you want to replace single quotes with escaped single quotes, you need to escape more to get past the specialness of \':
s.gsub("'", "\\\\'")
Or avoid the toothpicks and use the block form:
s.gsub("'") { |m| '\\' + m }
You would run into similar issues if you were trying to escape backticks, a plus sign, or even a single digit.
The overall lesson here is to prefer the block form of gsub for anything but the most trivial of substitutions.
s = "#main = 'quotes'
s.gsub "'", "\\\\'"
Since \it's \\equivalent if you want to get a double backslash you have to put four of ones.
You need to escape the \ as well:
s.gsub "'", "\\\\'"
Outputs
"#main= \\'quotes\\'"
A good explanation found on an outside forum:
The key point to understand IMHO is that a backslash is special in
replacement strings. So, whenever one wants to have a literal
backslash in a replacement string one needs to escape it and hence
have [two] backslashes. Coincidentally a backslash is also special in a
string (even in a single quoted string). So you need two levels of
escaping, makes 2 * 2 = 4 backslashes on the screen for one literal
replacement backslash.
source

How to split a string with "\" using ruby?

Lets say I have a string:
str = "12345\56789"
How to split above string into 2 words?
["12345","56789"]
str = "12345/56789"
print str.split('/') # => ["12345", "56789"]
Edit: With the change to a backslash, it should be:
str = '12345\56789'
print str.split('\\') # => ["12345", "56789"]
You need the double backslash to avoid escaping the closing quote mark.
Regexp.quote returns a string with special characters escaped. This returned string can be split with '\\'.
So the solution is: Regexp.quote('00050\00050').split('\\')[0]

How do I get this piece of code to match through regex using variables?

I am trying to find matches in some code using regex.
String I am using
"input[type=radio],input[type=checkbox] {"
To match this I added escape characters for every bracket:
"input\[type=radio\],input\[type=checkbox\] \{"
And I am running .match to find a match in a particular line of code:
"input[type=radio],input[type=checkbox] {".match(/input\[type=radio\],input\[type=checkbox\] \{/)
Which works. But when I turn them into variables, it doesn't.
str = "input[type=radio],input[type=checkbox] {"
code_to_match_against = "input\[type=radio\],input\[type=checkbox\] \{"
str.match(/#{code_to_match_against}/) # => nil
What am I doing wrong?
The double quotes in here:
code_to_match_against = "input\[type=radio\],input\[type=checkbox\] \{"
are eating your backslashes. Consider this:
>> code_to_match_against = "input\[type=radio\],input\[type=checkbox\] \{"
>> p code_to_match_against
"input[type=radio],input[type=checkbox] {"
So when you interpolate code_to_match_against into your regex, the regex engine thinks you're using two character classes:
/input[type=radio],input[type=checkbox] {/
# ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
and character classes match only one character at a time (unless you append * or +).
Either double your backslashes to get them past the double quotes or use single quotes instead:
>> code_to_match_against = 'input\[type=radio\],input\[type=checkbox\] \{'
>> p code_to_match_against
"input\\[type=radio\\],input\\[type=checkbox\\] \\{"
>> puts code_to_match_against
input\[type=radio\],input\[type=checkbox\] \{

Replace single quote with backslash single quote

I have a very large string that needs to escape all the single quotes in it, so I can feed it to JavaScript without upsetting it.
I have no control over the external string, so I can't change the source data.
Example:
Cote d'Ivoir -> Cote d\'Ivoir
(the actual string is very long and contains many single quotes)
I'm trying to this by using gsub on the string, but can't get this to work:
a = "Cote d'Ivoir"
a.gsub("'", "\\\'")
but this gives me:
=> "Cote dIvoirIvoir"
I also tried:
a.gsub("'", 92.chr + 39.chr)
but got the same result; I know it's something to do with regular expressions, but I never get those.
The %q delimiters come in handy here:
# %q(a string) is equivalent to a single-quoted string
puts "Cote d'Ivoir".gsub("'", %q(\\\')) #=> Cote d\'Ivoir
The problem is that \' in a gsub replacement means "part of the string after the match".
You're probably best to use either the block syntax:
a = "Cote d'Ivoir"
a.gsub(/'/) {|s| "\\'"}
# => "Cote d\\'Ivoir"
or the Hash syntax:
a.gsub(/'/, {"'" => "\\'"})
There's also the hacky workaround:
a.gsub(/'/, '\#').gsub(/#/, "'")
# prepare a text file containing [ abcd\'efg ]
require "pathname"
backslashed_text = Pathname("/path/to/the/text/file.txt").readlines.first.strip
# puts backslashed_text => abcd\'efg
unslashed_text = "abcd'efg"
unslashed_text.gsub("'", Regexp.escape(%q|\'|)) == backslashed_text # true
# puts unslashed_text.gsub("'", Regexp.escape(%q|\'|)) => abcd\'efg

Escaping '“' with regular double quotes using Ruby regex

I have text that has these fancy double quotes: '“' and I would like to replace them with regular double quotes using Ruby gsub and regex. Here's an example and what I have so far:
sentence = 'This is a quote, “Hey guys!”'
I couldn't figure out how to escape double quotes so I tried using 34.chr:
sentence.gsub("“",34.chr). This gets me close but leaves a back slash in front of the double quote:
sentence.gsub("“",34.chr) => 'This is a quote, \"Hey guys!”'
The backslashes are only showing up in irb due to the way it prints out the result of a statement. If you instead pass the gsubed string to another method such as puts, you'll see the "real" representation after escape sequences are translated.
1.9.0 > sentence = 'This is a quote, “Hey guys!”'
=> "This is a quote, \342\200\234Hey guys!\342\200\235"
1.9.0 > sentence.gsub('“', "'")
=> "This is a quote, 'Hey guys!\342\200\235"
1.9.0 > puts sentence.gsub('“', "'")
This is a quote, 'Hey guys!”
=> nil
Note also that after the output of puts, we see => nil indicating that the call to puts returned nil.
You probably noticed that the funny quote is still on the end of the output to puts: this is because the quotes are two different escape sequences, and we only named one. But we can take care of that with a regex in gsub:
1.9.0 > puts sentence.gsub(/(“|”)/, 34.chr)
This is a quote, "Hey guys!"
=> nil
Also, in many cases you can swap single quotes and double quotes in Ruby strings -- double quotes perform expansion while single quotes do not. Here are a couple ways you can get a string containing just a double quote:
1.9.0 > '"' == 34.chr
=> true
1.9.0 > %q{"} == 34.chr
=> true
1.9.0 > "\"" == 34.chr
=> true

Resources