Weird Backslash Substitution in Ruby

Weird backslash substitution in Ruby

This is an issue because backslash (\) serves as an escape character for Regexps and Strings. You could do use the special variable \& to reduce the number backslashes in the gsub replacement string.

foo.gsub(/\\/,'\&\&\&') #for some string foo replace each \ with \\\

EDIT: I should mention that the value of \& is from a Regexp match, in this case a single backslash.

Also, I thought that there was a special way to create a string that disabled the escape character, but apparently not. None of these will produce two slashes:

puts "\\"
puts '\\'
puts %q{\\}
puts %Q{\\}
puts """\\"""
puts '''\\'''
puts <<EOF

How to perform String replacements without backslash escaping in Ruby

Eventually I found pretty simple solution:

input = '{"regex": "/^\\\\([0-3][0-9]\\\\)$/"}'
puts input # gives => {"regex": "/^\\([0-3][0-9]\\)$/"}

search = '/^\\\\([0-3][0-9]\\\\)$/'
replace = '/^\\\\([0-9]\\\\)$/'

puts input.sub(search, replace) # gives => {"regex": "/^\([0-9]\)$/"}, which is wrong result

input[search] = replace # <-- here is the trick, but makes changes in place
puts input # gives => {"regex": "/^\\([0-9]\\)$/"} => success!

But! If your string doesn't contain any search substring you will get an string not matched (IndexError).

So you may want to bulletproof your code like this:

input[search] = replace if input.include? search

Also, if you want to keep your input untouched you may .dup it to another variable:

new_input = input.dup
new_input[search] = replace if new_input.include? search

backslash at end of string causes error when inserting into InfluxDB

You just use parameterized query strings:

INSERT INTO my_db.default.my_measurement,my_tag=1 my_val=%{1}

Where when you call it you do this:

influxdb.query("...query...", params: [ string ])

What you did was create a classic injection bug by sending unescaped data into a query. The same principle applies in any database with a plain-text string representation, or even other data formats like HTML and JavaScript.

What's the point of escaping a single backslash in single quotes in Ruby?

backslashes are an escape character so if you were to write '\' would think you were trying to escape the '.

Otherwise if it treated single character strings differentls you wanted to write ' you would have to use double quotes, which will quickly get harder to maintain when you need to remember which quotes to use when.

Gsub causing part of string to be substituted

It happens because "\\'" has a special meaning when it occurs as the replacement argument of gsub, namely it means the post-match substring.

To do what you want, you can use a block:

# => "abc \\'def\\' ghi"

Notice that the backslash is escaped in the string inspection, so it appears as \\.

How come you can't gsub this string in Ruby?

You are falling into the trap of a different meaning of escapes when used in strings with double quotes vs single quotes. Double-quoted strings allow escape characters to be used. Thus, here "\n" actually is a one-character string containing a single line feed. Compare that to '\n' which is a two-character string containing a literal backslash followed by a character n.

This explains, whey your gsub doesn't match. If you use the following code, it should work:


For your actual issue, you can use this

string = "R3pQvDqmz/EQ7zho2mhIeE6UB4dLa6GUH7173VEMdGCcdsRm5pernkqCgbnj\\nZjTX\\n"
new_string = string.gsub("\\n", "\n")

Replace & to \& in Ruby seems impossible?

Your linked question provides a solution - use the block form of gsub:

irb(main):009:0> puts "asdf & asdf".gsub("&"){'\&'}
asdf \& asdf

How to replace & with \& with gsub on rails?

Use triple \ in the replacement string:

print 'Company & Co. KG'.gsub('&', '\\\&')
# Company \& Co. KG=> nil

You can check that a single backslash is added by checking the length of both strings:

'Company & Co. KG'.size
# => 16
'Company & Co. KG'.gsub('&', '\\\&').size
# => 17

To understand it better, read about escaping:

  • Weird backslash substitution in Ruby


\& is a backreference to the whole match (like \0)

'Company & Co. KG'.gsub(/Co/, '-\&-')
# => "-Co-mpany & -Co-. KG"
'Company & Co. KG'.gsub(/Co/, '-\0-')
# => "-Co-mpany & -Co-. KG"

Ruby double slash gsub issue

The following works for me. Have you tried it in the terminal? It could be unescaped when you output the result.

> a = "<<<patent-inv>>>"
> a.gsub("<<<patent-inv>>>", "part1\\\\part2")
=> "part1\\part2"

You can see how the output varies between puts and p

> puts a
> p a
> puts a.inspect

EDIT Here is the output displayed as you want it.

1.9.2-p290 :037 > a.gsub!("<<<patent-inv>>>", "part1\\\\\\part2")
=> "part1\\\\part2"
> p a
=> "part1\\\\part2"
> puts a
=> nil

We know that 4 backslashes when changed equals 2 backslashes when unescaped. So 4 backslashes need to be generated AFTER the substitution for it to be displayed correctly.

Non-regexp version of gsub in Ruby

There are two layers of escaping for the second parameter of gsub:

The first layer is Ruby string constant. If it is written like \\\\\\ it is unescaped by Ruby like \\\

the second layer is gsub itself: \\\ is treated like \\ + \

double backslash is resolved into single: \\ => \ and the single trailing backslash at the end is resolved as itself.

8 backslashes are parsed in the similar way:

"\\\\\\\\" => "\\\\"

and then

"\\\\" => "\\"

so the constants consisting of six and eight backslashes are resolved into two backslashes.

To make life a bit easier, a block may be used in gsub function. String constants in a block are passed only through Ruby layer (thanks to @Sorrow).

"foo\\bar".gsub("\\") {"\\\\"}

Related Topics

Leave a reply