2

I am attempting to write a simple function to perform string interpolation on arbitrary text in ruby. I also want the function to not evaluate escaped interpolation blocks so that "\#{foo}" would be converted to "#{foo}" rather than evaluated.

When I pass an expression with an escaped block, the value appears correct when I use the puts method, but includes the escape character when I use p. I don't understand why.

Here is my code:

def evil_mark text
  part = text.partition(/[^\\]\#{.*?}/)
  return_string = part[0]
  until part[1] == ""
     return_string << eval("\"" + part[1] + "\"")
     part = evil_mark(part[2]).partition(/[^\\]\#{.*?}/)
     return_string << part[0]
  end
  return_string.gsub!(/\\\#{.*?}/){|s| s[1..-1]}
  return return_string
end

$foo = 'faz'
$bar = 'baz'

s = 'This is some \#{$foo} bar and some #{$bar} bat'

puts evil_mark s
#~> This is some #{$foo} bar and some baz bat

p evil_mark s
#~> "This is some \#{$foo} bar and some baz bat"

By the way, I understand that it can be dangerous to use the eval method.

dan_paul
  • 309
  • 1
  • 10

2 Answers2

2

Nothing is wrong with the return. The only reason it still appears escaped when using #p is that p prints the string is such a way as that it could essentially be used directly as ruby code for that string. - that is to say #p adds the escape back in on purpose.

azgult
  • 542
  • 3
  • 10
1

See p vs puts in Ruby, which says that p foo is not actually shorthand for puts foo but for puts foo.inspect. The value of some_object.inspect is going to show you the internals of the object, which are usually not the same as the string representation of the object. For example:

irb(main):004:0> "hello".inspect
=> "\"hello\""
irb(main):006:0> p "hello"
"hello"
=> "hello"
irb(main):005:0> puts "hello"
hello
=> nil

Notice how p includes the quotes the same way that inspect does (though inspect shows them suitably escaped), while puts does not?

The major difference is that inspect will always show the internals of the object, while puts will call to_s (if it exists, otherwise there is a default to_s that is used).

Community
  • 1
  • 1
Moshe Katz
  • 15,992
  • 7
  • 69
  • 116