我有这段代码:
settings[:base_name].gsub! /[\x00\/\\:\*\?\"<>\|]/, ''
当我运行脚本时,它会抛出一个错误:
gsub!': can't modify frozen String (RuntimeError)
我已将代码更改为:
settings[:base_name] = settings[:base_name].gsub /[\x00\/\\:\*\?\"<>\|]/, ''
上面的代码有效,但我完全不喜欢,有没有办法正确使用gsub!在这种情况下?
答案 0 :(得分:7)
没有。显然,提供字符串的API已将其冻结,这意味着修改它的任何方法都将失败。由于gsub!
修改了调用它的字符串,因此冻结对象无法使用gsub!
。但是,包含冻结对象的变量仍然可以设置为非冻结对象,这就是您的第二个代码段工作的原因。
API可能会冻结对象,因为它是所有实例共享的常量字符串,因此一个实例不应该破坏该字符串。但它们确实定义了一个setter方法,因此您可以设置该值。
答案 1 :(得分:4)
@pabloelices,
问题是String
引用的settings[:base_name]
对象已经frozen,现在实际上是不可变的。您可以通过以下方式查看:
settings[:base_name].frozen? # => will return 'true'
您可以通过执行以下操作来清理代码和意图:
my_setting = settings[:base_name].dup # Create a duplicate of the setting.
settings[:base_name] = my_setting.gsub /[\x00\/\\:\*\?\"<>\|]/, ''
但原始的String
对象不允许在其上调用gsub!
。