我正在尝试编写一个简单的函数来对ruby中的任意文本执行字符串插值。我还希望函数不评估转义插值块,以便“\#{foo}”转换为“#{foo}”而不是评估。
当我使用转义块传递表达式时,使用puts
方法时该值显示正确,但在使用p
时包含转义字符。我不明白为什么。
这是我的代码:
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"
顺便说一句,我知道使用eval
方法会很危险。
答案 0 :(得分:2)
回归没有问题。使用#p时它仍然出现转义的唯一原因是p打印字符串的方式是它本质上可以直接用作该字符串的ruby代码。 - 也就是说#p故意将逃跑添加回来。
答案 1 :(得分:1)
请参阅p vs puts in Ruby,其中p foo
实际上并不是puts foo
的简写,而是puts foo.inspect
的简写。 some_object.inspect
的值将显示对象的内部结构,通常与对象的字符串表示形式不同。例如:
irb(main):004:0> "hello".inspect
=> "\"hello\""
irb(main):006:0> p "hello"
"hello"
=> "hello"
irb(main):005:0> puts "hello"
hello
=> nil
请注意p
如何包含引号与inspect
的引用方式相同(尽管inspect
显示它们适当地转义),而puts
则没有?
主要区别在于inspect
将始终显示对象的内部,而puts
将调用to_s
(如果存在,则默认为to_s
用的)。