在内部使用`gsub`(双引号)heredoc不起作用

Don*_*ato 2 ruby heredoc literals

似乎gsub在(双引号)heredoc内部使用不会评估结果gsub,如下所示:

class Test
  def self.define_phone
    class_eval <<-EOS
      def _phone=(val)
        puts val
        puts val.gsub(/\D/,'')
      end
    EOS
  end
end

Test.define_phone
test = Test.new
test._phone = '123-456-7890'
# >> 123-456-7890
# >> 123-456-7890
Run Code Online (Sandbox Code Playgroud)

第二个puts应该打印1234567890,就像在这种情况下一样:

'123-456-7890'.gsub(/\D/,'')
 # => "1234567890" 
Run Code Online (Sandbox Code Playgroud)

heredoc里面发生了什么?

Len*_*ran 5

问题出\D在正则表达式中.当heredoc被评估为字符串时,将对其进行评估,结果是D:

"\D" # => "D"
eval("/\D/") #=> /D/
Run Code Online (Sandbox Code Playgroud)

另一方面,\D单个报价内部不会被评估为D:

'\D' # => "\\D"
eval('/\D/') # => /\D/ 
Run Code Online (Sandbox Code Playgroud)

因此,将heredoc终结符包装EOS在单引号中以实现您想要的:

class Test
  def self.define_phone
    class_eval <<-'EOS'
      def _phone=(val)
        puts val
        puts val.gsub(/\D/,'')
      end
    EOS
  end
end

Test.define_phone
test = Test.new
test._phone = '123-456-7890'
# >> 123-456-7890
# >> 1234567890
Run Code Online (Sandbox Code Playgroud)

参考

如果你运行上面的代码没有包装EOS,gsub将尝试替换"D"(字面意思)val.看到这个:

test._phone = '123-D456-D7890DD'
# >> 123-D456-D7890DD
# >> 123-456-7890
Run Code Online (Sandbox Code Playgroud)

  • 或者,另一种方法是用`\\ D`替换`\ D`. (3认同)