【问题标题】:Using `gsub` inside (double quoted) heredoc does not work在(双引号)heredoc 中使用 `gsub` 不起作用
【发布时间】:2019-04-27 16:48:05
【问题描述】:

似乎在(双引号)heredoc 中使用gsub 不会评估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

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

'123-456-7890'.gsub(/\D/,'')
 # => "1234567890" 

heredoc 里面发生了什么?

【问题讨论】:

  • 请注意,您可以在没有类 eval 的情况下完成此操作(因此不必担心字符串转义)。只需将class_evaldef _phone 替换为define_method :_phone do |val|

标签: ruby literals heredoc


【解决方案1】:

问题在于正则表达式中的\D。当heredoc被评估为字符串时,它将被评估,这导致D

"\D" # => "D"
eval("/\D/") #=> /D/

另一方面,单引号内的\D 不会被评估为D

'\D' # => "\\D"
eval('/\D/') # => /\D/ 

因此,将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

Reference

如果您在没有包装EOS 的情况下运行上述代码,gsub 将尝试替换val 中的“D”(字面意思)。看到这个:

test._phone = '123-D456-D7890DD'
# >> 123-D456-D7890DD
# >> 123-456-7890

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多