How to keep single backslash in Ruby string after to_json formating?
My apologies, you do seem to have a valid issue on your hand. The key is this: Why is the slash an escapable character in JSON? and its duplicate target, JSON: why are forward slashes escaped?. Since both unescaped slashes and escaped slashes are allowed, Ruby chose to not escape them, and PHP chose to escape them, and both approaches are correct.
(Aside: there's a bit of a complication in talking about this because \
is an escape character both for a string literal, and for JSON strings. Thus, in this answer, I take care to puts
(or echo
/print_r
) all the values, to see the strings that do not have the string literal backslash escapes, only the backslashes that are actually present in the strings.)
Thus, the JSON {"url":"http:\/\/example.com\/test"}
is a representation of the Ruby hash { 'url' => 'http://example.com/test' }
, where slashes are escaped (as PHP's json_encode
would do it). Ruby's to_json' would render that as
{"url":"http://example.com/test"}`:
# Ruby
json1 = '{"url":"http:\/\/example.com\/test"}'
puts json1 # => {"url":"http:\/\/example.com\/test"}
puts JSON.parse(json1) # => {"url"=>"http://example.com/test"}
puts JSON.parse(json1).to_json # => {"url":"http://example.com/test"}
# PHP
$json1 = '{"url":"http:\/\/example.com\/test"}';
echo $json1; # {"url":"http:\/\/example.com\/test"}
print_r(json_decode($json1)); # stdClass Object
# (
# [url] => http://example.com/test
# )
echo json_encode(json_decode($json1)); # {"url":"http:\/\/example.com\/test"}
On the other hand, {"url":"http:\\/\\/example.com\\/test"}
(represented in Ruby and PHP as the string '{"url":"http:\\\\/\\\\/example.com\\\\/test"}'
) is a representation of the Ruby hash { 'url' => 'http:\/\/example.com\/test' }
, where there are actual backslashes, but the slashes are not escaped. PHP's json_encode
would render this value as {"url":"http:\\\/\\\/example.com\\\/test"}
.
# Ruby
json2 = '{"url":"http:\\\\/\\\\/example.com\\\\/test"}'
puts json2 # => {"url":"http:\\/\\/example.com\\/test"}
puts JSON.parse(json2) # => {"url"=>"http:\\/\\/example.com\\/test"}
puts JSON.parse(json2).to_json # => {"url":"http:\\/\\/example.com\\/test"}
# PHP
$json2 = '{"url":"http:\\\\/\\\\/example.com\\\\/test"}';
echo $json2; # {"url":"http:\/\/example.com\/test"}
print_r(json_decode($json2)); # stdClass Object
# (
# [url] => http:\/\/example.com\/test
# )
echo json_encode(json_decode($json2)); # {"url":"http:\\\/\\\/example.com\\\/test"}
PHP json_encode
has an option to prevent the PHP's default of escaping of backslashes:
# PHP
echo json_encode('/'); # "\/"
echo json_encode('/', JSON_UNESCAPED_SLASHES); # "/"
Ruby does not have a similar option to force escaping of slashes, but since a slash has no special meaning in JSON, we can just manually replace /
with \/
:
# Ruby
puts '/'.to_json # "/"
puts '/'.to_json.gsub('/', '\/') # "\/"
How to print backslash in single quoted string in ruby
So long as the strings share the same encoding, byte comparison would be elegant solution without the need for additional escaping.
str.bytes == other.bytes
To display a backslash, you simply escape it with a single backslash:
puts '\\'
\
Additionally, depending on your exact usage, could use the <=>
operator:
(str <=> other).zero?
EDIT
To expand a little more, there is a difference in what is displayed to you if you just did something like this:
a = '\\'
p a
=> '\\'
This will show itself as two backslashes, but it is still in fact a single character, not two.
a = '\\'
a.bytes
=> [92] # ASCII code for a backslash (single byte)
How to print a string with a backward slash in Ruby
UPDATED answer:
escape token '\' is always working in plain ruby code, but not always working in "ruby console". so I suggest you write a unit test:
# escape_token_test.rb
require 'test/unit'
class EscapeTokenTest < Test::Unit::TestCase
def test_how_to_escape
hi = "hi\\backslash"
puts hi
end
end
and you will get result as:
hi\backslash
and see @pst's comment.
How to gsub slash / with back slash and slash \/ in ruby
Yes
irb(main):028:0> (t = x.gsub("/", "\\/")) && nil
=> nil
irb(main):029:0> t
=> "\\/foo\\/bar\\/dir"
irb(main):030:0> puts t
\/foo\/bar\/dir
=> nil
Your first example actually did what you wanted, but the .inspect
method that irb is using is escaping backslashes, so it looked like there were extras. If you had used puts
you would have seen the real result.
How to split a string by slash in ruby
Problem
Your tmp variable is enclosed in double-quotes, and contains a backslash which is being interpreted as an escape rather than a character literal. You can see this easily by simply pasting your string into a REPL like irb:
"DESKTOP-AHDESI\Username" #=> "DESKTOP-AHDESIUsername"
You need to handle the backslash specially in both your String methods.
Solution
One way to handle this is to use Ruby's alternate quoting mechanism. For example:
%q(DESKTOP-AHDESI\Username).split '\\' #=> ["DESKTOP-AHDESI", "Username"]
This may not help you directly, though.
Wherever the value from tmp is coming from, you need to refactor the code to ensure that your String is properly escaped before you assign it to your variable, or otherwise pre-process it. String#dump won't really help much if the value you're assigning is unescaped before assignment, so you're going to have to fix this in whatever code you're using to generate or grab the string in the first place.
I try to replace the backward slash with forward slash using gsub but it's not working
The problem is not with the #gsub
, but with the string construction itself:
"C:\WATIR\gopal\**" # => "C:WATIRgopal**"
\
is used for escaping character. \W
for example will try go escape the W
character, instead of make two characters - \
and W
. One way to fix it is to escape the escaping with another \
:
"C:\\WATIR\\gopal\\**" # => "C:\\WATIR\\gopal\\**"
The better way is to use single quotes, where \
has no special meaning:
'C:\WATIR\gopal\**' # => "C:\\WATIR\\gopal\\**"
Additionally, prefer #tr
over #gsub
when you want to replace a single character with another:
'C:\WATIR\gopal\**'.tr('\\', '/') # => "C:/WATIR/gopal/**"
How to define a ruby array that contains a backslash(\) character?
There are some characters which are special and need to be escaped.
Like when you define a string
str = " this is test string \
and this contains multiline data \
do you understand the backslash meaning here \
it is being used to denote the continuation of line"
In a string defined in a double quotes "", if you need to have a double quote how would you doo that? "\"", this is why when you put a backslash in a string you are telling interpretor you are going to use some special characters and which are escaped by backslash. So when you read a "\" from a file it will be read as "\" this into a ruby string.
char = "\\"
char.length # => 1
I hope this helps ;)
Related Topics
How to Force Rails to Load All Models
Devise Not Displaying Error Messge During an Authentication Failure
Positive Lookahead Doesn't Stop at First Occurrence
(New to Rails) Rails Server Error: Cannot Load Such File -- Bootsnap/Setup (Loaderror)
Getting Current Line of Code in Ruby
Automatic Associations in Ruby on Rails Fixtures
How to Run "Bundle Exec Jekyll New ."
Ruby - Test Whether Database Connection Is Possible
Returning True or Error Message in Ruby
Lion Osx: How to Install Libfreetype.6.Dylib
Why Is Bigdecimal Returning a Weird Value
Require': Cannot Load Such File -- Spec_Helper (Loaderror)
Ruby on Rails Activerecord Scopes VS Class Methods
Rails 4: How to Upload Files with Ajax
Validates_Inclusion_Of No Longer Working the Same in Rails 4.1