首页 > 解决方案 > 在(双引号)heredoc 中使用 `gsub` 不起作用

问题描述

似乎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

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

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

heredoc 内部发生了什么?

标签: rubyliteralsheredoc

解决方案


问题出\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

参考

如果您在没有包装的情况下运行上述代码EOSgsub将尝试替换val. 看到这个:

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

推荐阅读