user1038486
user1038486

Reputation: 13

Ruby: Strings do not match

I am testing two strings to see if they are equal. One string is just a simple string: "\17" The other is parsed to: "\17"

num = 7
num2 = "\17"

parsed_num = "\1#{num}"

puts parsed_num.class
puts num2.class

if parsed_num == num2
  puts 'Equal'
else
  puts 'Not equal'
end

It returns:

String

String

Not equal

My goal is to have parsed_num exactly the same as the literal num2

Upvotes: 1

Views: 521

Answers (3)

user166390
user166390

Reputation:

I am going to take the opposite answer and assume that "\17" is correct, then consider this code:

num = 7
num2 = "\17"
puts "ni  #{num2.inspect}"

# extra \ to fix error, for demo
parsed_num = "\\1#{num}"
puts "pi  #{parsed_num.inspect}"

# for note, but ICK!!!
p2 = eval('"' + parsed_num + '"')
puts "p2i #{p2.inspect}"
puts "p2= #{p2 == num2}"

dec = (10 + num).to_s.oct
p3 = dec.chr
puts "p3i #{p3.inspect}"
puts "p3= #{p3 == num2}"

Result:

ni  "\017"
pi  "\\17"
p2i "\017"
p2= true
p3i "\017"
p3= true

The reason why "\1#{num}" didn't work is that string literals -- and the embedded escape sequences -- are handled during parsing while the string interpolation itself (#{}) happens later, at run-time. (This is required, because who knows what may happen to be in num?)

In the case of p2 I used eval, which parses and then executes the supplied code. The code there is equivalent to eval('"\17"'), because parsed_num contained the 3-letter string: \17. (Please note, this approach is generally considered bad!)

In the case of p3 I manually did what the parser does for string interpolation of \octal: took the value of octal, in, well, octal, and then converted it into the "character" with the corresponding value.

Happy coding.

Upvotes: 3

WarHog
WarHog

Reputation: 8710

If you're using "\17" backslash escape, it will be interpreted as as "\0017", where 17 would be an octal digit equals to 'F' hex:

"\17"  # => "\u000F"

because your string uses double quotes.

You can achieve what you want with help of this snippet, for example:

num = 7
num2 = "\\17"
parsed_num = "\\1#{num}"
if parsed_num == num2
  puts 'Equal'
else
  puts 'Not equal'
end
# => Equal

As you can see you get this result with help of the backslash to escape another backslash :)

Upvotes: 3

Chris Bunch
Chris Bunch

Reputation: 89903

Use single quotes so that the strings involved are the literal things you are setting:

num = 7
num2 = '\17'

parsed_num = '\1' + String(num)
if parsed_num == num2
  puts 'Equal'
else
  puts 'Not equal'
end

This produces 'Equal' - the desired result. Here's a link with more info on the differences between single quoted strings and double quoted strings if desired.

Upvotes: 1

Related Questions