我想确切地知道在这两种情况下 #gsub 调用期间如何更新字符串对象的内部字符串缓冲区:
- 没有进行替换。例如
"hello".gsub!('r', 'a')
. - 搜索字符串和替换字符串的字节长度完全相同。例如,
"hello".gsub!('e', 'a')
。
在这两种情况下,#gsub 会不会创建一个新的字符串缓冲区,将原来的缓冲区复制到新的缓冲区,然后扔掉原来的?还是会在原地完成替换?
我想确切地知道在这两种情况下 #gsub 调用期间如何更新字符串对象的内部字符串缓冲区:
"hello".gsub!('r', 'a')
."hello".gsub!('e', 'a')
。在这两种情况下,#gsub 会不会创建一个新的字符串缓冲区,将原来的缓冲区复制到新的缓冲区,然后扔掉原来的?还是会在原地完成替换?
MRI 有一种方法str_gsub
可以同时处理gsub
和gsub!
,具体取决于最后一个参数:
static VALUE str_gsub(int argc, VALUE *argv, VALUE str, int bang)
如果未找到匹配项,则该方法将返回nil
( gsub!
) 或字符串 ( ) 的副本gsub
:
beg = rb_reg_search(pat, str, 0, 0);
if (beg < 0) {
if (bang) return Qnil; /* no match, no substitution */
return rb_str_dup(str);
}
否则,将创建一个新的字符串缓冲区:
dest = rb_str_buf_new(blen);
然后执行替换,然后替换字符串 ( gsub!
) 或返回新实例 ( gsub
):
if (bang) {
rb_str_shared_replace(str, dest);
}
else {
RBASIC(dest)->klass = rb_obj_class(str);
OBJ_INFECT(dest, str);
str = dest;
}
if (tainted) OBJ_TAINT(str);
return str;