4

我有这个代码:

 settings[:base_name].gsub! /[\x00\/\\:\*\?\"<>\|]/, ''

当我运行脚本时,它会引发错误:

gsub!': can't modify frozen String (RuntimeError)

我已将代码更改为:

 settings[:base_name] = settings[:base_name].gsub /[\x00\/\\:\*\?\"<>\|]/, ''

上面的代码有效,但我一点也不喜欢,有没有办法正确使用gsub!在这种情况下?

4

2 回答 2

7

不。显然,提供字符串的 API 已将其冻结,这意味着任何修改它的方法都会失败。因为gsub!修改了调用它的字符串,冻结的对象不能使用gsub!. 但是,包含冻结对象的变量仍然可以设置为非冻结对象,这就是您的第二个代码片段有效的原因。

API 可能冻结了该对象,因为它是所有实例共享的常量字符串,因此一个实例不应破坏该字符串。但他们确实定义了一个 setter 方法,因此您可以设置该值。

于 2012-08-29T17:50:34.227 回答
5

@pabloelice,

问题是String引用的对象settings[:base_name]已被冻结,现在实际上是不可变的。您可以通过以下方式检查:

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!在其上调用。

于 2012-08-29T17:55:38.673 回答