класс String
Объект String хранит и обрабатывает произвольную последовательность байтов, обычно представляющую символы. Объекты String могут быть созданы с помощью String::new или как литералы.
Из-за проблем с алиасингом пользователи строк должны быть осведомлены о методах, которые изменяют содержимое объекта String. Как правило, методы с именами, оканчивающимися на «!», изменяют свой получатель, в то время как методы без «!» возвращают новый объект String. Однако есть исключения, такие как String#[]=.
Публичные методы экземпляра
# File ext/nkf/lib/kconv.rb, line 264 def iseuc; Kconv.iseuc(self) end
Возвращает значение true, если кодировка self равна EUC-JP, и false в противном случае.
# File ext/nkf/lib/kconv.rb, line 276 def isjis; Kconv.isjis(self) end
Возвращает значение true, если кодировка self равна ISO-2022-JP, и false в противном случае.
# File ext/nkf/lib/kconv.rb, line 270 def issjis; Kconv.issjis(self) end
Возвращает значение true, если кодировка self равна Shift_JIS, и false в противном случае.
# File ext/nkf/lib/kconv.rb, line 282 def isutf8; Kconv.isutf8(self) end
Возвращает значение true, если кодировка self равна UTF-8, и false в противном случае.
# File ext/nkf/lib/kconv.rb, line 205 def kconv(to_enc, from_enc=nil) from_enc = self.encoding if !from_enc && self.encoding != Encoding.list[0] Kconv::kconv(self, to_enc, from_enc) end
Преобразовать self в to_enc. to_enc и from_enc задаются как константы объектов Kconv или Encoding.
static VALUE
string_to_c(VALUE self)
{
char *s;
VALUE num;
rb_must_asciicompat(self);
s = RSTRING_PTR(self);
if (s && s[RSTRING_LEN(self)]) {
rb_str_modify(self);
s = RSTRING_PTR(self);
s[RSTRING_LEN(self)] = '\0';
}
if (!s)
s = (char *)"";
(void)parse_comp(s, 0, &num);
return num;
} Возвращает комплексное число, обозначающее строковую форму. Парсер игнорирует ведущие пробелы и хвостовой мусор. Любые числовые последовательности могут быть разделены нижним подчёркиванием. Возвращает ноль для пустой или повреждённой строки.
'9'.to_c #=> (9+0i) '2.5'.to_c #=> (2.5+0i) '2.5/1'.to_c #=> ((5/2)+0i) '-3/2'.to_c #=> ((-3/2)+0i) '-i'.to_c #=> (0-1i) '45i'.to_c #=> (0+45i) '3-4i'.to_c #=> (3-4i) '-4e2-4e-2i'.to_c #=> (-400.0-0.04i) '-0.0-0.0i'.to_c #=> (-0.0-0.0i) '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i) 'ruby'.to_c #=> (0+0i)
См. Kernel.Complex.
# File ext/nkf/lib/kconv.rb, line 224 def toeuc; Kconv.toeuc(self) end
Преобразует self в EUC-JP.
# File ext/nkf/lib/kconv.rb, line 218 def tojis; Kconv.tojis(self) end
Преобразует self в ISO-2022-JP.
# File ext/nkf/lib/kconv.rb, line 254 def tolocale; Kconv.tolocale(self) end
Преобразует self в кодировку по умолчанию.
# File ext/nkf/lib/kconv.rb, line 230 def tosjis; Kconv.tosjis(self) end
Преобразует self в Shift_JIS.
# File ext/nkf/lib/kconv.rb, line 242 def toutf16; Kconv.toutf16(self) end
Преобразует self в UTF-16.
# File ext/nkf/lib/kconv.rb, line 248 def toutf32; Kconv.toutf32(self) end
Преобразует self в UTF-32.
# File ext/nkf/lib/kconv.rb, line 236 def toutf8; Kconv.toutf8(self) end
Преобразует self в UTF-8.
scanf
↑ вверхПубличные методы класса
static VALUE
rb_str_init(int argc, VALUE *argv, VALUE str)
{
static ID keyword_ids[2];
VALUE orig, opt, venc, vcapa;
VALUE kwargs[2];
rb_encoding *enc = 0;
int n;
if (!keyword_ids[0]) {
keyword_ids[0] = rb_id_encoding();
CONST_ID(keyword_ids[1], "capacity");
}
n = rb_scan_args(argc, argv, "01:", &orig, &opt);
if (!NIL_P(opt)) {
rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
venc = kwargs[0];
vcapa = kwargs[1];
if (venc != Qundef && !NIL_P(venc)) {
enc = rb_to_encoding(venc);
}
if (vcapa != Qundef && !NIL_P(vcapa)) {
long capa = NUM2LONG(vcapa);
long len = 0;
int termlen = enc ? rb_enc_mbminlen(enc) : 1;
if (capa < STR_BUF_MIN_SIZE) {
capa = STR_BUF_MIN_SIZE;
}
if (n == 1) {
StringValue(orig);
len = RSTRING_LEN(orig);
if (capa < len) {
capa = len;
}
if (orig == str) n = 0;
}
str_modifiable(str);
if (STR_EMBED_P(str)) { /* make noembed always */
RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)capa + termlen);
}
else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
(size_t)capa + termlen, STR_HEAP_SIZE(str));
}
RSTRING(str)->as.heap.len = len;
TERM_FILL(&RSTRING(str)->as.heap.ptr[len], termlen);
if (n == 1) {
memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), len);
rb_enc_cr_str_exact_copy(str, orig);
}
FL_SET(str, STR_NOEMBED);
RSTRING(str)->as.heap.aux.capa = capa;
}
else if (n == 1) {
rb_str_replace(str, orig);
}
if (enc) {
rb_enc_associate(str, enc);
ENC_CODERANGE_CLEAR(str);
}
}
else if (n == 1) {
rb_str_replace(str, orig);
}
return str;
} Возвращает новый объект строки, содержащий копию str.
Необязательный аргумент encoding задаёт кодировку новой строки. Если он не указан, используется кодировка str (или ASCII-8BIT, если str не указан).
Необязательный аргумент capacity задаёт размер внутреннего буфера. Это может улучшить производительность, когда строка будет многократно конкатенироваться (вызывая много вызовов realloc).
static VALUE
rb_str_s_try_convert(VALUE dummy, VALUE str)
{
return rb_check_string_type(str);
} Попытаться преобразовать obj в String, используя метод to_str. Возвращает преобразованную строку или nil, если obj не может быть преобразован по какой-либо причине.
String.try_convert("str") #=> "str"
String.try_convert(/re/) #=> nil
Публичные методы экземпляров
static VALUE
rb_str_format_m(VALUE str, VALUE arg)
{
VALUE tmp = rb_check_array_type(arg);
if (!NIL_P(tmp)) {
return rb_str_format(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp), str);
}
return rb_str_format(1, &arg, str);
} Форматирование — Использует str в качестве спецификации формата и возвращает результат её применения к arg. Если спецификация формата содержит более одной подстановки, то arg должен быть Array или Hash, содержащим значения для подстановки. Подробнее см. Kernel::sprintf.
"%05d" % 123 #=> "00123"
"%-5s: %016x" % [ "ID", self.object_id ] #=> "ID : 00002b054ec93168"
"foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"
VALUE
rb_str_times(VALUE str, VALUE times)
{
VALUE str2;
long n, len;
char *ptr2;
int termlen;
if (times == INT2FIX(1)) {
return rb_str_dup(str);
}
if (times == INT2FIX(0)) {
str2 = str_alloc(rb_obj_class(str));
rb_enc_copy(str2, str);
OBJ_INFECT(str2, str);
return str2;
}
len = NUM2LONG(times);
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
str2 = str_alloc(rb_obj_class(str));
if (!STR_EMBEDDABLE_P(len, 1)) {
RSTRING(str2)->as.heap.aux.capa = len;
RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
STR_SET_NOEMBED(str2);
}
STR_SET_LEN(str2, len);
rb_enc_copy(str2, str);
OBJ_INFECT(str2, str);
return str2;
}
if (len && LONG_MAX/len < RSTRING_LEN(str)) {
rb_raise(rb_eArgError, "argument too big");
}
len *= RSTRING_LEN(str);
termlen = TERM_LEN(str);
str2 = str_new0(rb_obj_class(str), 0, len, termlen);
ptr2 = RSTRING_PTR(str2);
if (len) {
n = RSTRING_LEN(str);
memcpy(ptr2, RSTRING_PTR(str), n);
while (n <= len/2) {
memcpy(ptr2 + n, ptr2, n);
n *= 2;
}
memcpy(ptr2 + n, ptr2, len-n);
}
STR_SET_LEN(str2, len);
TERM_FILL(&ptr2[len], termlen);
OBJ_INFECT(str2, str);
rb_enc_cr_str_copy_for_substr(str2, str);
return str2;
} Копирование — Возвращает новый String, содержащий integer копий объекта-приемника. integer должно быть больше или равно 0.
"Ho! " * 3 #=> "Ho! Ho! Ho! " "Ho! " * 0 #=> ""
VALUE
rb_str_plus(VALUE str1, VALUE str2)
{
VALUE str3;
rb_encoding *enc;
char *ptr1, *ptr2, *ptr3;
long len1, len2;
int termlen;
StringValue(str2);
enc = rb_enc_check_str(str1, str2);
RSTRING_GETMEM(str1, ptr1, len1);
RSTRING_GETMEM(str2, ptr2, len2);
termlen = rb_enc_mbminlen(enc);
if (len1 > LONG_MAX - len2) {
rb_raise(rb_eArgError, "string size too big");
}
str3 = str_new0(rb_cString, 0, len1+len2, termlen);
ptr3 = RSTRING_PTR(str3);
memcpy(ptr3, ptr1, len1);
memcpy(ptr3+len1, ptr2, len2);
TERM_FILL(&ptr3[len1+len2], termlen);
FL_SET_RAW(str3, OBJ_TAINTED_RAW(str1) | OBJ_TAINTED_RAW(str2));
ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
RB_GC_GUARD(str1);
RB_GC_GUARD(str2);
return str3;
} Конкатенация — Возвращает новый String, содержащий other_str, конкатенированный с str.
"Hello from " + self.to_s #=> "Hello from main"
static VALUE
str_uplus(VALUE str)
{
if (OBJ_FROZEN(str)) {
return rb_str_dup(str);
}
else {
return str;
}
} Если строка заморожена, возвращает дублированную мутабельную строку.
Если строка не заморожена, возвращает саму строку.
static VALUE
str_uminus(VALUE str)
{
return rb_fstring(str);
} Возвращает замороженную, возможно уже существующую копию строки.
Строка будет дедуплицирована, пока она не помечена как изменённая или не имеет установленных экземпляров переменных.
VALUE
rb_str_concat(VALUE str1, VALUE str2)
{
unsigned int code;
rb_encoding *enc = STR_ENC_GET(str1);
int encidx;
if (RB_INTEGER_TYPE_P(str2)) {
if (rb_num_to_uint(str2, &code) == 0) {
}
else if (FIXNUM_P(str2)) {
rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2));
}
else {
rb_raise(rb_eRangeError, "bignum out of char range");
}
}
else {
return rb_str_append(str1, str2);
}
encidx = rb_enc_to_index(enc);
if (encidx == ENCINDEX_ASCII || encidx == ENCINDEX_US_ASCII) {
/* US-ASCII automatically extended to ASCII-8BIT */
char buf[1];
buf[0] = (char)code;
if (code > 0xFF) {
rb_raise(rb_eRangeError, "%u out of char range", code);
}
rb_str_cat(str1, buf, 1);
if (encidx == ENCINDEX_US_ASCII && code > 127) {
rb_enc_associate_index(str1, ENCINDEX_ASCII);
ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID);
}
}
else {
long pos = RSTRING_LEN(str1);
int cr = ENC_CODERANGE(str1);
int len;
char *buf;
switch (len = rb_enc_codelen(code, enc)) {
case ONIGERR_INVALID_CODE_POINT_VALUE:
rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
break;
case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
case 0:
rb_raise(rb_eRangeError, "%u out of char range", code);
break;
}
buf = ALLOCA_N(char, len + 1);
rb_enc_mbcput(code, buf, enc);
if (rb_enc_precise_mbclen(buf, buf + len + 1, enc) != len) {
rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
}
rb_str_resize(str1, pos+len);
memcpy(RSTRING_PTR(str1) + pos, buf, len);
if (cr == ENC_CODERANGE_7BIT && code > 127)
cr = ENC_CODERANGE_VALID;
ENC_CODERANGE_SET(str1, cr);
}
return str1;
} Добавляет заданный объект к str. Если объект является Integer, он рассматривается как код символа и преобразуется в символ перед добавлением.
a = "hello " a << "world" #=> "hello world" a << 33 #=> "hello world!"
См. также String#concat, принимающий несколько аргументов.
static VALUE
rb_str_cmp_m(VALUE str1, VALUE str2)
{
int result;
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
return rb_invcmp(str1, str2);
}
result = rb_str_cmp(str1, s);
return INT2FIX(result);
} Сравнение — Возвращает -1, 0, +1 или nil, в зависимости от того, является ли string меньше, равно или больше other_string.
Возвращает nil, если два значения несравнимы.
Если строки имеют разную длину, и строки равны при сравнении до наименьшей длины, то более длинная строка считается большей, чем более короткая.
<=> служит основой для методов <, <=, >, >=, и between?, включённых из модуля Comparable. Метод String#== не использует Comparable#==.
"abcdef" <=> "abcde" #=> 1 "abcdef" <=> "abcdef" #=> 0 "abcdef" <=> "abcdefg" #=> -1 "abcdef" <=> "ABCDEF" #=> 1 "abcdef" <=> 1 #=> nil
VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) {
if (!rb_respond_to(str2, idTo_str)) {
return Qfalse;
}
return rb_equal(str2, str1);
}
return str_eql(str1, str2);
} Равенство — Возвращает, равны ли str и obj, аналогично Object#==.
Если obj не является экземпляром String, но отвечает на to_str, то две строки сравниваются с помощью obj.==.
В противном случае, возвращает значение, аналогичное String#eql?, сравнивая длину и содержимое.
VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) {
if (!rb_respond_to(str2, idTo_str)) {
return Qfalse;
}
return rb_equal(str2, str1);
}
return str_eql(str1, str2);
} Равенство — Возвращает, равны ли str и obj, аналогично Object#==.
Если obj не является экземпляром String, но отвечает на to_str, то две строки сравниваются с помощью obj.==.
В противном случае, возвращает значение, аналогичное String#eql?, сравнивая длину и содержимое.
static VALUE
rb_str_match(VALUE x, VALUE y)
{
if (SPECIAL_CONST_P(y)) goto generic;
switch (BUILTIN_TYPE(y)) {
case T_STRING:
rb_raise(rb_eTypeError, "type mismatch: String given");
case T_REGEXP:
return rb_reg_match(y, x);
generic:
default:
return rb_funcall(y, idEqTilde, 1, x);
}
} Сопоставление — Если obj является Regexp, используйте его как шаблон для сопоставления с str и возвращает позицию начала совпадения или nil, если совпадения нет. В противном случае вызывает obj.=~, передавая str в качестве аргумента. По умолчанию =~ в Object возвращает nil.
Примечание: str =~ regexp не то же самое, что и regexp =~ str. Строки, захваченные из именованных групп захвата, присваиваются локальным переменным только во втором случае.
"cat o' 9 tails" =~ /\d/ #=> 7 "cat o' 9 tails" =~ 9 #=> nil
static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
return rb_str_subpat(str, argv[0], argv[1]);
}
else {
long beg = NUM2LONG(argv[0]);
long len = NUM2LONG(argv[1]);
return rb_str_substr(str, beg, len);
}
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0]);
} Ссылка на элемент — Если передано одно index, возвращает подстроку длиной один символ в указанном индексе. Если переданы начальный индекс start и длина length, возвращает подстроку, содержащую length символа, начиная с индекса start. Если передано range, его начало и конец интерпретируются как смещения, определяющие подстроку, которая должна быть возвращена.
В этих трёх случаях, если индекс отрицательный, он отсчитывается с конца строки. Для случаев start и range начальный индекс находится перед символом, а индекс, соответствующий размеру строки. Кроме того, пустая строка возвращается, когда начальный индекс диапазона символов находится в конце строки.
Возвращает nil, если начальный индекс выходит за пределы строки или длина отрицательная.
Если предоставлен Regexp, возвращается соответствующая часть строки. Если за регулярным выражением следует capture, который может быть индексом или именем группы захвата, возвращается соответствующая часть объекта MatchData.
Если задана match_str, возвращается эта строка, если она встречается в строке.
Возвращает nil, если регулярное выражение не соответствует или строка совпадения не найдена.
a = "hello there" a[1] #=> "e" a[2, 3] #=> "llo" a[2..3] #=> "ll" a[-3, 2] #=> "er" a[7..-2] #=> "her" a[-4..-2] #=> "her" a[-2..-4] #=> "" a[11, 0] #=> "" a[11] #=> nil a[12, 0] #=> nil a[12..-1] #=> nil a[/[aeiou](.)\1/] #=> "ell" a[/[aeiou](.)\1/, 0] #=> "ell" a[/[aeiou](.)\1/, 1] #=> "l" a[/[aeiou](.)\1/, 2] #=> nil a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l" a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"] #=> "e" a["lo"] #=> "lo" a["bye"] #=> nil
static VALUE
rb_str_aset_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 3) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
}
else {
rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
}
return argv[2];
}
rb_check_arity(argc, 2, 3);
return rb_str_aset(str, argv[0], argv[1]);
} Присвоение элемента — Заменяет часть или всё содержимое str. Часть строки, на которую влияет операция, определяется по тем же критериям, что и String#[]. Если длина заменяющей строки отличается от длины заменяемой части, строка будет соответствующим образом скорректирована. Если регулярное выражение или строка используются в качестве индекса и не соответствуют позиции в строке, генерируется IndexError. В случае использования регулярного выражения, необязательный второй Integer позволяет указать, какую часть совпадения заменить (фактически используя правила индексации MatchData). Формы, принимающие Integer, генерируют IndexError, если значение находится за пределами допустимого диапазона; форма Range генерирует RangeError, а формы Regexp и String генерируют IndexError при отрицательном результате сопоставления.
static VALUE
rb_str_is_ascii_only_p(VALUE str)
{
int cr = rb_enc_str_coderange(str);
return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse;
} Возвращает true для строки, содержащей только символы ASCII.
"abc".force_encoding("UTF-8").ascii_only? #=> true
"abc\u{6666}".force_encoding("UTF-8").ascii_only? #=> false
static VALUE
rb_str_b(VALUE str)
{
VALUE str2 = str_alloc(rb_cString);
str_replace_shared_without_enc(str2, str);
OBJ_INFECT_RAW(str2, str);
ENC_CODERANGE_CLEAR(str2);
return str2;
} Возвращает скопированную строку, кодировка которой ASCII-8BIT.
# File lib/scanf.rb, line 753
def block_scanf(fstr) #:yield: current_match
fs = Scanf::FormatString.new(fstr)
str = self.dup
final = []
begin
current = str.scanf(fs)
final.push(yield(current)) unless current.empty?
str = fs.string_left
end until current.empty? || str.empty?
return final
end Сканирует текущую строку до тех пор, пока совпадение не будет исчерпано, передавая каждое совпадение по мере его обнаружения в строке. Блок не является обязательным, так как результаты будут просто агрегированы в итоговый массив.
"123 456".block_scanf("%d")
# => [123, 456]
Если задан блок, значение, возвращаемое из него yield, добавляется в выходной массив.
"123 456".block_scanf("%d) do |digit,| # the ',' unpacks the Array
digit + 100
end
# => [223, 556] См. Scanf для получения подробной информации о создании форматированной строки.
Вам нужно будет использовать require 'scanf', чтобы использовать String#block_scanf
static VALUE
rb_str_bytes(VALUE str)
{
VALUE ary = WANTARRAY("bytes", RSTRING_LEN(str));
return rb_str_enumerate_bytes(str, ary);
} Возвращает массив байтов в str. Это сокращение для str.each_byte.to_a.
Если задан блок, который является устаревшей формой, работает так же, как each_byte.
static VALUE
rb_str_bytesize(VALUE str)
{
return LONG2NUM(RSTRING_LEN(str));
} Возвращает длину str в байтах.
"\x80\u3042".bytesize #=> 4 "hello".bytesize #=> 5
static VALUE
rb_str_byteslice(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
long beg = NUM2LONG(argv[0]);
long end = NUM2LONG(argv[1]);
return str_byte_substr(str, beg, end, TRUE);
}
rb_check_arity(argc, 1, 2);
return str_byte_aref(str, argv[0]);
} Byte Reference—Если передан один Integer, возвращает подстроку из одного байта в этой позиции. Если передано два объекта Integer, возвращает подстроку, начинающуюся с смещения, заданного первым, и длиной, заданной вторым. Если задан Range, возвращается подстрока, содержащая байты со смещениями, заданными диапазоном. Во всех трех случаях, если смещение отрицательное, оно отсчитывается от конца str. Возвращает nil, если начальное смещение выходит за пределы строки, длина отрицательна или начало диапазона больше конца. Кодировка результирующей строки сохраняет исходную кодировку.
"hello".byteslice(1) #=> "e" "hello".byteslice(-1) #=> "o" "hello".byteslice(1, 2) #=> "el" "\x80\u3042".byteslice(1, 3) #=> "\u3042" "\x03\u3042\xff".byteslice(1..3) #=> "\u3042"
static VALUE
rb_str_capitalize(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_capitalize_bang(argc, argv, str);
return str;
} Возвращает копию str с первым символом, преобразованным в верхний регистр, а остальными — в нижний регистр.
См. String#downcase для значения options и использования с различными кодировками.
"hello".capitalize #=> "Hello" "HELLO".capitalize #=> "Hello" "123ABC".capitalize #=> "123abc"
static VALUE
rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Модифицирует str, преобразуя первый символ в верхний регистр, а остальную часть — в нижний регистр. Возвращает nil, если изменения не были внесены. Существует исключение для современного грузинского (мхедрули/MTAVRULI), где результат такой же, как для String#downcase, чтобы избежать смешанного регистра.
См. String#downcase для значения options и использования с различными кодировками.
a = "hello" a.capitalize! #=> "Hello" a #=> "Hello" a.capitalize! #=> nil
static VALUE
rb_str_casecmp(VALUE str1, VALUE str2)
{
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
return Qnil;
}
return str_casecmp(str1, s);
} Версия String#<=> без учёта регистра. В настоящее время регистронезависимость работает только для символов A-Z/a-z, а не для всего Unicode. Это отличается от String#casecmp?.
"aBcDeF".casecmp("abcde") #=> 1
"aBcDeF".casecmp("abcdef") #=> 0
"aBcDeF".casecmp("abcdefg") #=> -1
"abcdef".casecmp("ABCDEF") #=> 0
nil возвращается, если две строки имеют несовместимые кодировки или если other_str не является строкой.
"foo".casecmp(2) #=> nil
"\u{e4 f6 fc}".encode("ISO-8859-1").casecmp("\u{c4 d6 dc}") #=> nil
static VALUE
rb_str_casecmp_p(VALUE str1, VALUE str2)
{
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
return Qnil;
}
return str_casecmp_p(str1, s);
} Возвращает true, если str и other_str равны после сворачивания регистра Unicode, false, если они не равны.
"aBcDeF".casecmp?("abcde") #=> false
"aBcDeF".casecmp?("abcdef") #=> true
"aBcDeF".casecmp?("abcdefg") #=> false
"abcdef".casecmp?("ABCDEF") #=> true
"\u{e4 f6 fc}".casecmp?("\u{c4 d6 dc}") #=> true
nil возвращается, если две строки имеют несовместимые кодировки или если other_str не является строкой.
"foo".casecmp?(2) #=> nil
"\u{e4 f6 fc}".encode("ISO-8859-1").casecmp?("\u{c4 d6 dc}") #=> nil
static VALUE
rb_str_center(int argc, VALUE *argv, VALUE str)
{
return rb_str_justify(argc, argv, str, 'c');
} Центрирует str в width. Если width больше длины str, возвращает новый String длиной width с str, центрированным и дополненным padstr; в противном случае возвращает str.
"hello".center(4) #=> "hello" "hello".center(20) #=> " hello " "hello".center(20, '123') #=> "1231231hello12312312"
static VALUE
rb_str_chars(VALUE str)
{
VALUE ary = WANTARRAY("chars", rb_str_strlen(str));
return rb_str_enumerate_chars(str, ary);
} Возвращает массив символов в str. Это сокращение для str.each_char.to_a.
Если задан блок, который является устаревшей формой, работает так же, как each_char.
static VALUE
rb_str_chomp(int argc, VALUE *argv, VALUE str)
{
VALUE rs = chomp_rs(argc, argv);
if (NIL_P(rs)) return rb_str_dup(str);
return rb_str_subseq(str, 0, chompped_length(str, rs));
} Возвращает новый String с удалённым разделителем записей с конца str (если он присутствует). Если $/ не был изменен со значения разделителя записей по умолчанию Ruby, то chomp также удаляет символы возврата каретки (то есть он удалит \n, \r и \r\n). Если $/ является пустой строкой, он удалит все конечные символы перевода строки из строки.
"hello".chomp #=> "hello"
"hello\n".chomp #=> "hello"
"hello\r\n".chomp #=> "hello"
"hello\n\r".chomp #=> "hello\n"
"hello\r".chomp #=> "hello"
"hello \n there".chomp #=> "hello \n there"
"hello".chomp("llo") #=> "he"
"hello\r\n\r\n".chomp('') #=> "hello"
"hello\r\n\r\r\n".chomp('') #=> "hello\r\n\r"
static VALUE
rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
{
VALUE rs;
str_modifiable(str);
if (RSTRING_LEN(str) == 0) return Qnil;
rs = chomp_rs(argc, argv);
if (NIL_P(rs)) return Qnil;
return rb_str_chomp_string(str, rs);
} Модифицирует str на месте, как описано для String#chomp, возвращая str или nil, если модификации не были выполнены.
static VALUE
rb_str_chop(VALUE str)
{
return rb_str_subseq(str, 0, chopped_length(str));
} Возвращает новый String с удаленным последним символом. Если строка заканчивается на \r\n, оба символа удаляются. Применение chop к пустой строке возвращает пустую строку. String#chomp часто является более безопасной альтернативой, так как она оставляет строку неизменной, если она не заканчивается разделителем записей.
"string\r\n".chop #=> "string" "string\n\r".chop #=> "string\n" "string\n".chop #=> "string" "string".chop #=> "strin" "x".chop.chop #=> ""
static VALUE
rb_str_chop_bang(VALUE str)
{
str_modify_keep_cr(str);
if (RSTRING_LEN(str) > 0) {
long len;
len = chopped_length(str);
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
ENC_CODERANGE_CLEAR(str);
}
return str;
}
return Qnil;
} Обрабатывает str как для String#chop, возвращая str или nil, если str является пустой строкой. См. также String#chomp!.
static VALUE
rb_str_chr(VALUE str)
{
return rb_str_substr(str, 0, 1);
} Возвращает строку из одного символа в начале строки.
a = "abcde" a.chr #=> "a"
static VALUE
rb_str_clear(VALUE str)
{
str_discard(str);
STR_SET_EMBED(str);
STR_SET_EMBED_LEN(str, 0);
RSTRING_PTR(str)[0] = 0;
if (rb_enc_asciicompat(STR_ENC_GET(str)))
ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
else
ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
return str;
} Делает строку пустой.
a = "abcde" a.clear #=> ""
static VALUE
rb_str_codepoints(VALUE str)
{
VALUE ary = WANTARRAY("codepoints", rb_str_strlen(str));
return rb_str_enumerate_codepoints(str, ary);
} Возвращает массив Integer порядковых номеров символов в str. Это сокращение для str.each_codepoint.to_a.
Если задан блок (устаревшая форма), работает так же, как each_codepoint.
static VALUE
rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
{
str_modifiable(str);
if (argc == 1) {
return rb_str_concat(str, argv[0]);
}
else if (argc > 1) {
int i;
VALUE arg_str = rb_str_tmp_new(0);
rb_enc_copy(arg_str, str);
for (i = 0; i < argc; i++) {
rb_str_concat(arg_str, argv[i]);
}
rb_str_buf_append(str, arg_str);
}
return str;
} Конкатенирует заданный объект(ы) к str. Если объект является Integer, он рассматривается как кодовая точка и преобразуется в символ перед конкатенацией.
concat может принимать несколько аргументов, и все аргументы конкатенируются по порядку.
a = "hello "
a.concat("world", 33) #=> "hello world!"
a #=> "hello world!"
b = "sn"
b.concat("_", b, "_", b) #=> "sn_sn_sn"
См. также String#<<, который принимает один аргумент.
static VALUE
rb_str_count(int argc, VALUE *argv, VALUE str)
{
char table[TR_TABLE_SIZE];
rb_encoding *enc = 0;
VALUE del = 0, nodel = 0, tstr;
char *s, *send;
int i;
int ascompat;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
tstr = argv[0];
StringValue(tstr);
enc = rb_enc_check(str, tstr);
if (argc == 1) {
const char *ptstr;
if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
(ptstr = RSTRING_PTR(tstr),
ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (const unsigned char *)ptstr, (const unsigned char *)ptstr+1)) &&
!is_broken_string(str)) {
int n = 0;
int clen;
unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
send = RSTRING_END(str);
while (s < send) {
if (*(unsigned char*)s++ == c) n++;
}
return INT2NUM(n);
}
}
tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
for (i=1; i<argc; i++) {
tstr = argv[i];
StringValue(tstr);
enc = rb_enc_check(str, tstr);
tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
}
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
send = RSTRING_END(str);
ascompat = rb_enc_asciicompat(enc);
i = 0;
while (s < send) {
unsigned int c;
if (ascompat && (c = *(unsigned char*)s) < 0x80) {
if (table[c]) {
i++;
}
s++;
}
else {
int clen;
c = rb_enc_codepoint_len(s, send, &clen, enc);
if (tr_find(c, table, del, nodel)) {
i++;
}
s += clen;
}
}
return INT2NUM(i);
} Каждый параметр other_str определяет набор символов для подсчета. Пересечение этих множеств определяет символы для подсчета в str. Любой other_str, начинающийся со знака каретки ^, инвертируется. Последовательность c1-c2 означает все символы между c1 и c2. Символ обратной косой черты \ может использоваться для экранирования ^ или - и в противном случае игнорируется, если он не появляется в конце последовательности или в конце other_str.
a = "hello world" a.count "lo" #=> 5 a.count "lo", "o" #=> 2 a.count "hello", "^l" #=> 4 a.count "ej-m" #=> 4 "hello^world".count "\\^aeiou" #=> 4 "hello-world".count "a\\-eo" #=> 4 c = "hello world\\r\\n" c.count "\\" #=> 2 c.count "\\A" #=> 0 c.count "X-\\w" #=> 3
static VALUE
rb_str_crypt(VALUE str, VALUE salt)
{
#ifdef HAVE_CRYPT_R
VALUE databuf;
struct crypt_data *data;
# define CRYPT_END() ALLOCV_END(databuf)
#else
extern char *crypt(const char *, const char *);
# define CRYPT_END() (void)0
#endif
VALUE result;
const char *s, *saltp;
char *res;
#ifdef BROKEN_CRYPT
char salt_8bit_clean[3];
#endif
StringValue(salt);
mustnot_wchar(str);
mustnot_wchar(salt);
if (RSTRING_LEN(salt) < 2) {
short_salt:
rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
}
s = StringValueCStr(str);
saltp = RSTRING_PTR(salt);
if (!saltp[0] || !saltp[1]) goto short_salt;
#ifdef BROKEN_CRYPT
if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
salt_8bit_clean[0] = saltp[0] & 0x7f;
salt_8bit_clean[1] = saltp[1] & 0x7f;
salt_8bit_clean[2] = '\0';
saltp = salt_8bit_clean;
}
#endif
#ifdef HAVE_CRYPT_R
data = ALLOCV(databuf, sizeof(struct crypt_data));
# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
data->initialized = 0;
# endif
res = crypt_r(s, saltp, data);
#else
res = crypt(s, saltp);
#endif
if (!res) {
int err = errno;
CRYPT_END();
rb_syserr_fail(err, "crypt");
}
result = rb_str_new_cstr(res);
CRYPT_END();
FL_SET_RAW(result, OBJ_TAINTED_RAW(str) | OBJ_TAINTED_RAW(salt));
return result;
} Возвращает строку, сгенерированную вызовом стандартной библиотечной функции crypt(3) с str и salt_str, в этом порядке, в качестве аргументов. Пожалуйста, больше не используйте этот метод. Он устарел; предоставлен только для обратной совместимости со скриптами ruby более ранних версий. Его плохо использовать в современных программах по нескольким причинам:
* Behaviour of C's <code>crypt(3)</code> depends on the OS it is
run. The generated string lacks data portability.
* On some OSes such as Mac OS, <code>crypt(3)</code> never fails
(i.e. silently ends up in unexpected results).
* On some OSes such as Mac OS, <code>crypt(3)</code> is not
thread safe.
* So-called "traditional" usage of <code>crypt(3)</code> is very
very very weak. According to its manpage, Linux's traditional
<code>crypt(3)</code> output has only 2**56 variations; too
easy to brute force today. And this is the default behaviour.
* In order to make things robust some OSes implement so-called
"modular" usage. To go through, you have to do a complex
build-up of the <code>salt_str</code> parameter, by hand.
Failure in generation of a proper salt string tends not to
yield any errors; typos in parameters are normally not
detectable.
* For instance, in the following example, the second invocation
of <code>String#crypt</code> is wrong; it has a typo in
"round=" (lacks "s"). However the call does not fail and
something unexpected is generated.
"foo".crypt("$5$rounds=1000$salt$") # OK, proper usage
"foo".crypt("$5$round=1000$salt$") # Typo not detected
* Even in the "modular" mode, some hash functions are considered
archaic and no longer recommended at all; for instance module
<code>$1$</code> is officially abandoned by its author: see
http://phk.freebsd.dk/sagas/md5crypt_eol.html . For another
instance module <code>$3$</code> is considered completely
broken: see the manpage of FreeBSD.
* On some OS such as Mac OS, there is no modular mode. Yet, as
written above, <code>crypt(3)</code> on Mac OS never fails.
This means even if you build up a proper salt string it
generates a traditional DES hash anyways, and there is no way
for you to be aware of.
"foo".crypt("$5$rounds=1000$salt$") # => "$5fNPQMxC5j6." Если по какой-либо причине вы не можете перейти на другие безопасные современные алгоритмы хеширования паролей, установите gem string-crypt и require 'string/crypt' для продолжения его использования.
static VALUE
rb_str_delete(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_delete_bang(argc, argv, str);
return str;
} Возвращает копию str со всеми символами в пересечении его аргументов, удаленными. Использует те же правила для построения множества символов, что и String#count.
"hello".delete "l","lo" #=> "heo" "hello".delete "lo" #=> "he" "hello".delete "aeiou", "^e" #=> "hell" "hello".delete "ej-m" #=> "ho"
static VALUE
rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
{
char squeez[TR_TABLE_SIZE];
rb_encoding *enc = 0;
char *s, *send, *t;
VALUE del = 0, nodel = 0;
int modify = 0;
int i, ascompat, cr;
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i=0; i<argc; i++) {
VALUE s = argv[i];
StringValue(s);
enc = rb_enc_check(str, s);
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
str_modify_keep_cr(str);
ascompat = rb_enc_asciicompat(enc);
s = t = RSTRING_PTR(str);
send = RSTRING_END(str);
cr = ascompat ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
while (s < send) {
unsigned int c;
int clen;
if (ascompat && (c = *(unsigned char*)s) < 0x80) {
if (squeez[c]) {
modify = 1;
}
else {
if (t != s) *t = c;
t++;
}
s++;
}
else {
c = rb_enc_codepoint_len(s, send, &clen, enc);
if (tr_find(c, squeez, del, nodel)) {
modify = 1;
}
else {
if (t != s) rb_enc_mbcput(c, t, enc);
t += clen;
if (cr == ENC_CODERANGE_7BIT) cr = ENC_CODERANGE_VALID;
}
s += clen;
}
}
TERM_FILL(t, TERM_LEN(str));
STR_SET_LEN(str, t - RSTRING_PTR(str));
ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
} Выполняет операцию delete на месте, возвращая str или nil, если str не был изменен.
static VALUE
rb_str_delete_prefix(VALUE str, VALUE prefix)
{
long prefixlen;
prefixlen = deleted_prefix_length(str, prefix);
if (prefixlen <= 0) return rb_str_dup(str);
return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
} Возвращает копию str с удаленным ведущим prefix.
"hello".delete_prefix("hel") #=> "lo"
"hello".delete_prefix("llo") #=> "hello"
static VALUE
rb_str_delete_prefix_bang(VALUE str, VALUE prefix)
{
long prefixlen;
str_modify_keep_cr(str);
prefixlen = deleted_prefix_length(str, prefix);
if (prefixlen <= 0) return Qnil;
return rb_str_drop_bytes(str, prefixlen);
} Удаляет ведущий prefix из str, возвращая nil, если изменений не было.
"hello".delete_prefix!("hel") #=> "lo"
"hello".delete_prefix!("llo") #=> nil
static VALUE
rb_str_delete_suffix(VALUE str, VALUE suffix)
{
long suffixlen;
suffixlen = deleted_suffix_length(str, suffix);
if (suffixlen <= 0) return rb_str_dup(str);
return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
} Возвращает копию str с удаленным конечным suffix.
"hello".delete_suffix("llo") #=> "he"
"hello".delete_suffix("hel") #=> "hello"
static VALUE
rb_str_delete_suffix_bang(VALUE str, VALUE suffix)
{
long olen, suffixlen, len;
str_modifiable(str);
suffixlen = deleted_suffix_length(str, suffix);
if (suffixlen <= 0) return Qnil;
olen = RSTRING_LEN(str);
str_modify_keep_cr(str);
len = olen - suffixlen;
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
ENC_CODERANGE_CLEAR(str);
}
return str;
} Удаляет конечный suffix из str, возвращая nil, если изменений не было.
"hello".delete_suffix!("llo") #=> "he"
"hello".delete_suffix!("hel") #=> nil
static VALUE
rb_str_downcase(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_downcase_bang(argc, argv, str);
return str;
} Возвращает копию str со всеми заглавными буквами, замененными на их строчные аналоги. Какие именно буквы заменяются и на какие другие буквы, зависит от наличия или отсутствия параметров и от encoding строки.
Значение options следующее:
- Без параметров
-
Полное сопоставление регистров Unicode, подходящее для большинства языков (см. параметры :turkic и :lithuanian ниже для исключений). Контекстно-зависимое сопоставление регистров, как описано в таблице 3-14 стандарта Unicode, в настоящее время не поддерживается.
- :ascii
-
Влияет только на область ASCII, то есть символы «A» до «Z» и «a» до «z». Этот параметр не может сочетаться ни с каким другим параметром.
- :turkic
-
Полное сопоставление регистров Unicode, адаптированное для тюркских языков (турецкий, азербайджанский и т. д.). Это означает, что заглавная буква I отображается в строчную без точки i и так далее.
- :lithuanian
-
В настоящее время просто полное сопоставление регистров Unicode. В будущем полное сопоставление регистров Unicode, адаптированное для литовского языка (сохранение точки в строчной i, даже если сверху есть акцент).
- :fold
-
Доступно только для
downcaseиdowncase!. Свертка регистра Unicode, которая имеет более широкий охват, чем сопоставление регистра Unicode. В настоящее время этот параметр не может сочетаться ни с каким другим параметром (т. е. в настоящее время нет варианта для тюркских языков).
Обратите внимание, что несколько предположений, которые верны для преобразований регистра только в ASCII, не выполняются для более общих преобразований регистра. Например, длина результата может не совпадать с длиной входных данных (ни в символах, ни в байтах), некоторые предположения о возврате (например, str.downcase == str.upcase.downcase) могут не применяться, и нормализация Unicode (т. е. String#unicode_normalize) не обязательно поддерживается операциями сопоставления регистра.
Сопоставление/свертка регистра, отличная от ASCII, в настоящее время поддерживается для строк/символов UTF-8, UTF-16BE/LE, UTF-32BE/LE и ISO-8859-1~16. Эта поддержка будет расширена на другие кодировки.
"hEllO".downcase #=> "hello"
static VALUE
rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (((flags&ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() || rb_enc_mbmaxlen(enc)==1))
|| (!(flags&ONIGENC_CASE_FOLD_TURKISH_AZERI) && ENC_CODERANGE(str)==ENC_CODERANGE_7BIT)) {
char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
while (s < send) {
unsigned int c = *(unsigned char*)s;
if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
*s = 'a' + (c - 'A');
flags |= ONIGENC_CASE_MODIFIED;
}
s++;
}
}
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Преобразует содержимое str в нижний регистр, возвращая nil, если изменений не было.
См. String#downcase для значения options и использования с различными кодировками.
VALUE
rb_str_dump(VALUE str)
{
int encidx = rb_enc_get_index(str);
rb_encoding *enc = rb_enc_from_index(encidx);
long len;
const char *p, *pend;
char *q, *qend;
VALUE result;
int u8 = (encidx == rb_utf8_encindex());
static const char nonascii_suffix[] = ".dup.force_encoding(\"%s\")";
len = 2; /* "" */
if (!rb_enc_asciicompat(enc)) {
len += strlen(nonascii_suffix) - rb_strlen_lit("%s");
len += strlen(enc->name);
}
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
while (p < pend) {
int clen;
unsigned char c = *p++;
switch (c) {
case '"': case '\\':
case '\n': case '\r':
case '\t': case '\f':
case '\013': case '\010': case '\007': case '\033':
clen = 2;
break;
case '#':
clen = IS_EVSTR(p, pend) ? 2 : 1;
break;
default:
if (ISPRINT(c)) {
clen = 1;
}
else {
if (u8 && c > 0x7F) { /* \u notation */
int n = rb_enc_precise_mbclen(p-1, pend, enc);
if (MBCLEN_CHARFOUND_P(n)) {
unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
if (cc <= 0xFFFF)
clen = 6; /* \uXXXX */
else if (cc <= 0xFFFFF)
clen = 9; /* \u{XXXXX} */
else
clen = 10; /* \u{XXXXXX} */
p += MBCLEN_CHARFOUND_LEN(n)-1;
break;
}
}
clen = 4; /* \xNN */
}
break;
}
if (clen > LONG_MAX - len) {
rb_raise(rb_eRuntimeError, "string size too big");
}
len += clen;
}
result = rb_str_new_with_class(str, 0, len);
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
q = RSTRING_PTR(result); qend = q + len + 1;
*q++ = '"';
while (p < pend) {
unsigned char c = *p++;
if (c == '"' || c == '\\') {
*q++ = '\\';
*q++ = c;
}
else if (c == '#') {
if (IS_EVSTR(p, pend)) *q++ = '\\';
*q++ = '#';
}
else if (c == '\n') {
*q++ = '\\';
*q++ = 'n';
}
else if (c == '\r') {
*q++ = '\\';
*q++ = 'r';
}
else if (c == '\t') {
*q++ = '\\';
*q++ = 't';
}
else if (c == '\f') {
*q++ = '\\';
*q++ = 'f';
}
else if (c == '\013') {
*q++ = '\\';
*q++ = 'v';
}
else if (c == '\010') {
*q++ = '\\';
*q++ = 'b';
}
else if (c == '\007') {
*q++ = '\\';
*q++ = 'a';
}
else if (c == '\033') {
*q++ = '\\';
*q++ = 'e';
}
else if (ISPRINT(c)) {
*q++ = c;
}
else {
*q++ = '\\';
if (u8) {
int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
if (MBCLEN_CHARFOUND_P(n)) {
int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
p += n;
if (cc <= 0xFFFF)
snprintf(q, qend-q, "u%04X", cc); /* \uXXXX */
else
snprintf(q, qend-q, "u{%X}", cc); /* \u{XXXXX} or \u{XXXXXX} */
q += strlen(q);
continue;
}
}
snprintf(q, qend-q, "x%02X", c);
q += 3;
}
}
*q++ = '"';
*q = '\0';
if (!rb_enc_asciicompat(enc)) {
snprintf(q, qend-q, nonascii_suffix, enc->name);
encidx = rb_ascii8bit_encindex();
}
OBJ_INFECT_RAW(result, str);
/* result from dump is ASCII */
rb_enc_associate_index(result, encidx);
ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT);
return result;
} Создает версию str со всеми непечатаемыми символами, замененными на \nnn обозначение, и всеми специальными символами, экранированными.
"hello \n ''".dump #=> "\"hello \\n ''\""
static VALUE
rb_str_each_byte(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_byte_size);
return rb_str_enumerate_bytes(str, 0);
} Передает каждый байт в str заданному блоку или возвращает перечислитель, если блок не задан.
"hello".each_byte {|c| print c, ' ' }
выдает:
104 101 108 108 111
static VALUE
rb_str_each_char(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_char_size);
return rb_str_enumerate_chars(str, 0);
} Передает каждый символ в str заданному блоку или возвращает перечислитель, если блок не задан.
"hello".each_char {|c| print c, ' ' }
выдает:
h e l l o
static VALUE
rb_str_each_codepoint(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_char_size);
return rb_str_enumerate_codepoints(str, 0);
} Передает порядковый номер Integer каждого символа в str, также известный как codepoint при применении к строкам Юникода, в заданный блок. Для кодировок, отличных от UTF-8/UTF-16(BE|LE)/UTF-32(BE|LE), значения выводятся непосредственно из двоичного представления каждого символа.
Если блок не задан, возвращается перечислитель.
"hello\u0639".each_codepoint {|c| print c, ' ' }
выдает:
104 101 108 108 111 1593
static VALUE
rb_str_each_grapheme_cluster(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_grapheme_cluster_size);
return rb_str_enumerate_grapheme_clusters(str, 0);
} Передает каждый графемный кластер в str в заданный блок или возвращает перечислитель, если блок не задан. В отличие от String#each_char, этот перечислитель работает по графемным кластерам, определённым в Приложении #29 к стандарту Юникод unicode.org/reports/tr29/
"a\u0300".each_char.to_a.size #=> 2 "a\u0300".each_grapheme_cluster.to_a.size #=> 1
static VALUE
rb_str_each_line(int argc, VALUE *argv, VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, argc, argv, 0);
return rb_str_enumerate_lines(argc, argv, str, 0);
} Разбивает str с использованием заданного параметра в качестве разделителя записей ($/ по умолчанию), передавая каждую подстроку в заданный блок. Если разделитель записи имеет нулевую длину, строка разбивается на абзацы, ограниченные несколькими последовательными символами новой строки.
См. IO.readlines для получения информации о параметрах getline_args.
Если блок не задан, возвращается перечислитель.
print "Example one\n"
"hello\nworld".each_line {|s| p s}
print "Example two\n"
"hello\nworld".each_line('l') {|s| p s}
print "Example three\n"
"hello\n\n\nworld".each_line('') {|s| p s}
выдает:
Example one "hello\n" "world" Example two "hel" "l" "o\nworl" "d" Example three "hello\n\n" "world"
static VALUE
rb_str_empty(VALUE str)
{
if (RSTRING_LEN(str) == 0)
return Qtrue;
return Qfalse;
} Возвращает true если длина str равна нулю.
"hello".empty? #=> false " ".empty? #=> false "".empty? #=> true
static VALUE
str_encode(int argc, VALUE *argv, VALUE str)
{
VALUE newstr = str;
int encidx = str_transcode(argc, argv, &newstr);
return encoded_dup(newstr, str, encidx);
} Первый вариант возвращает копию str, транскодированную в кодировку encoding. Второй вариант возвращает копию str, транскодированную из src_encoding в dst_encoding. Последний вариант возвращает копию str, транскодированную в Encoding.default_internal.
По умолчанию первый и второй варианты вызывают Encoding::UndefinedConversionError для символов, не определённых в кодировке назначения, и Encoding::InvalidByteSequenceError для недопустимых последовательностей байтов в кодировке источника. Последний вариант по умолчанию не вызывает исключений, а использует строки замены.
Дополнительные параметры Hash предоставляют подробную информацию о преобразованиях и могут содержать следующие ключи:
- :invalid
-
Если значение равно
:replace,encodeзаменяет недопустимые последовательности байтов вstrна символ замены. По умолчанию возникает исключениеEncoding::InvalidByteSequenceError. - :undef
-
Если значение равно
:replace,encodeзаменяет символы, которые не определены в кодировке назначения, на символ замены. По умолчанию возникает исключениеEncoding::UndefinedConversionError. - :replace
-
Устанавливает строку замены на указанное значение. Значение строки замены по умолчанию — «uFFFD» для форм кодирования Юникода и «?» в противном случае.
- :fallback
-
Устанавливает строку замены с помощью указанного объекта для неопределённых символов. Объект должен быть
Hash,Proc,Methodили объектом, имеющим метод []. Его ключом является неопределённый символ, закодированный в кодировке источника текущего транскодера. Его значение может быть любой кодировкой, пока она может быть преобразована в кодировку назначения транскодера. - :xml
-
Значение должно быть
:textили:attr. Если значение равно:text,encodeзаменяет неопределённые символы на их числовые ссылки (в верхнем регистре шестнадцатеричные). '&', '<', и '>' преобразуются соответственно в «&», «<», и «>». Если значение равно:attr,encodeтакже приводит результат замены в кавычки (используя '“'), и заменяет '”' на «"». - :cr_newline
-
Заменяет LF («n») на CR («r»), если значение равно true.
- :crlf_newline
-
Заменяет LF («n») на CRLF («rn»), если значение равно true.
- :universal_newline
-
Заменяет CRLF («rn») и CR («r») на LF («n»), если значение равно true.
static VALUE
str_encode_bang(int argc, VALUE *argv, VALUE str)
{
VALUE newstr;
int encidx;
rb_check_frozen(str);
newstr = str;
encidx = str_transcode(argc, argv, &newstr);
if (encidx < 0) return str;
if (newstr == str) {
rb_enc_associate_index(str, encidx);
return str;
}
rb_str_shared_replace(str, newstr);
return str_encode_associate(str, encidx);
} Первый вариант транскодирует содержимое str из str.encoding в encoding. Второй вариант транскодирует содержимое str из src_encoding в dst_encoding. Параметры Hash предоставляют подробную информацию о преобразованиях. См. String#encode для получения дополнительной информации. Возвращает строку даже если изменения не были внесены.
VALUE
rb_obj_encoding(VALUE obj)
{
int idx = rb_enc_get_index(obj);
if (idx < 0) {
rb_raise(rb_eTypeError, "unknown encoding");
}
return rb_enc_from_encoding_index(idx & ENC_INDEX_MASK);
} Возвращает объект Encoding, который представляет кодировку объекта.
static VALUE
rb_str_end_with(int argc, VALUE *argv, VALUE str)
{
int i;
char *p, *s, *e;
rb_encoding *enc;
for (i=0; i<argc; i++) {
VALUE tmp = argv[i];
StringValue(tmp);
enc = rb_enc_check(str, tmp);
if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
p = RSTRING_PTR(str);
e = p + RSTRING_LEN(str);
s = e - RSTRING_LEN(tmp);
if (rb_enc_left_char_head(p, s, e, enc) != s)
continue;
if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
return Qtrue;
}
return Qfalse;
} Возвращает true, если str оканчивается на одну из suffixes заданных строк.
"hello".end_with?("ello") #=> true
# returns true if one of the +suffixes+ matches.
"hello".end_with?("heaven", "ello") #=> true
"hello".end_with?("heaven", "paradise") #=> false
MJIT_FUNC_EXPORTED VALUE
rb_str_eql(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
return str_eql(str1, str2);
} Две строки равны, если у них одинаковая длина и содержимое.
static VALUE
rb_str_force_encoding(VALUE str, VALUE enc)
{
str_modifiable(str);
rb_enc_associate(str, rb_to_encoding(enc));
ENC_CODERANGE_CLEAR(str);
return str;
} Изменяет кодировку на encoding и возвращает self.
VALUE
rb_str_freeze(VALUE str)
{
if (OBJ_FROZEN(str)) return str;
rb_str_resize(str, RSTRING_LEN(str));
return rb_obj_freeze(str);
} static VALUE
rb_str_getbyte(VALUE str, VALUE index)
{
long pos = NUM2LONG(index);
if (pos < 0)
pos += RSTRING_LEN(str);
if (pos < 0 || RSTRING_LEN(str) <= pos)
return Qnil;
return INT2FIX((unsigned char)RSTRING_PTR(str)[pos]);
} возвращает index-й байт как целое число.
static VALUE
rb_str_grapheme_clusters(VALUE str)
{
VALUE ary = WANTARRAY("grapheme_clusters", rb_str_strlen(str));
return rb_str_enumerate_grapheme_clusters(str, ary);
} Возвращает массив графемных кластеров в str. Это сокращение для str.each_grapheme_cluster.to_a.
Если задан блок, что является устаревшей формой, работает так же, как each_grapheme_cluster.
static VALUE
rb_str_gsub(int argc, VALUE *argv, VALUE str)
{
return str_gsub(argc, argv, str, 0);
} Возвращает копию str со всеми вхождениями pattern, заменёнными на второе значение. pattern обычно является Regexp; если задано как String, все метасимволы регулярных выражений в нём будут интерпретированы буквально, например, '\\d' будет соответствовать обратной косой черте, за которой следует 'd', вместо цифры.
Если replacement является String, то он будет заменён на совпавшее значение. Он может содержать обратные ссылки на группы захвата паттерна в формате \\d, где d - номер группы, или \\k<n>, где n - имя группы. Если это строка в двойных кавычках, обе обратные ссылки должны предшествовать дополнительной обратной косой чертой. Однако внутри replacement специальные переменные соответствия, такие как $&, не будут ссылаться на текущее соответствие.
Если второе значение является Hash, и совпавшее значение является одним из его ключей, соответствующее значение является строкой замены.
В форме с блоком текущая строка соответствия передаётся в качестве параметра, а такие переменные, как $1, $2, $`, $&, и $', будут установлены соответствующим образом. Значение, возвращаемое блоком, будет заменено на совпадение при каждом вызове.
Результат наследует все метки исходной строки или любой строки замены.
Когда не задан ни блок, ни второе значение, возвращается Enumerator.
"hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"
static VALUE
rb_str_gsub_bang(int argc, VALUE *argv, VALUE str)
{
str_modify_keep_cr(str);
return str_gsub(argc, argv, str, 1);
} Выполняет замены String#gsub на месте, возвращая str или nil, если замены не были выполнены. Если не задан ни блок, ни replacement, возвращается перечислитель вместо этого.
static VALUE
rb_str_hash_m(VALUE str)
{
st_index_t hval = rb_str_hash(str);
return ST2FIX(hval);
} Возвращает хэш, основанный на длине, содержании и кодировке строки.
См. также Object#hash.
static VALUE
rb_str_hex(VALUE str)
{
return rb_str_to_inum(str, 16, FALSE);
} Обрабатывает ведущие символы из str как строку шестнадцатеричных цифр (с необязательным знаком и необязательным 0x) и возвращает соответствующее число. В случае ошибки возвращается ноль.
"0x0a".hex #=> 10 "-1234".hex #=> -4660 "0".hex #=> 0 "wombat".hex #=> 0
static VALUE
rb_str_include(VALUE str, VALUE arg)
{
long i;
StringValue(arg);
i = rb_str_index(str, arg, 0);
if (i == -1) return Qfalse;
return Qtrue;
} Возвращает true, если str содержит заданную строку или символ.
"hello".include? "lo" #=> true "hello".include? "ol" #=> false "hello".include? ?h #=> true
static VALUE
rb_str_index_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE initpos;
long pos;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
pos = NUM2LONG(initpos);
}
else {
pos = 0;
}
if (pos < 0) {
pos += str_strlen(str, NULL);
if (pos < 0) {
if (RB_TYPE_P(sub, T_REGEXP)) {
rb_backref_set(Qnil);
}
return Qnil;
}
}
if (SPECIAL_CONST_P(sub)) goto generic;
switch (BUILTIN_TYPE(sub)) {
case T_REGEXP:
if (pos > str_strlen(str, NULL))
return Qnil;
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
rb_enc_check(str, sub), single_byte_optimizable(str));
pos = rb_reg_search(sub, str, pos, 0);
pos = rb_str_sublen(str, pos);
break;
generic:
default: {
VALUE tmp;
tmp = rb_check_string_type(sub);
if (NIL_P(tmp)) {
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_obj_classname(sub));
}
sub = tmp;
}
/* fall through */
case T_STRING:
pos = rb_str_index(str, sub, pos);
pos = rb_str_sublen(str, pos);
break;
}
if (pos == -1) return Qnil;
return LONG2NUM(pos);
} Возвращает индекс первого вхождения заданного substring или паттерна (regexp) в str. Возвращает nil, если не найдено. Если второй параметр присутствует, он задаёт позицию в строке, с которой начинать поиск.
"hello".index('e') #=> 1
"hello".index('lo') #=> 3
"hello".index('a') #=> nil
"hello".index(?e) #=> 1
"hello".index(/[aeiou]/, -3) #=> 4
VALUE
rb_str_replace(VALUE str, VALUE str2)
{
str_modifiable(str);
if (str == str2) return str;
StringValue(str2);
str_discard(str);
return str_replace(str, str2);
} Заменяет содержимое и метки str соответствующими значениями в other_str.
s = "hello" #=> "hello" s.replace "world" #=> "world"
static VALUE
rb_str_insert(VALUE str, VALUE idx, VALUE str2)
{
long pos = NUM2LONG(idx);
if (pos == -1) {
return rb_str_append(str, str2);
}
else if (pos < 0) {
pos++;
}
rb_str_splice(str, pos, 0, str2);
return str;
} Вставляет other_str перед символом в заданном index, изменяя str. Отрицательные индексы отсчитываются от конца строки и вставляются после данного символа. Цель - вставить aString так, чтобы он начинался в заданном index.
"abcd".insert(0, 'X') #=> "Xabcd" "abcd".insert(3, 'X') #=> "abcXd" "abcd".insert(4, 'X') #=> "abcdX" "abcd".insert(-3, 'X') #=> "abXcd" "abcd".insert(-1, 'X') #=> "abcdX"
VALUE
rb_str_inspect(VALUE str)
{
int encidx = ENCODING_GET(str);
rb_encoding *enc = rb_enc_from_index(encidx), *actenc;
const char *p, *pend, *prev;
char buf[CHAR_ESC_LEN + 1];
VALUE result = rb_str_buf_new(0);
rb_encoding *resenc = rb_default_internal_encoding();
int unicode_p = rb_enc_unicode_p(enc);
int asciicompat = rb_enc_asciicompat(enc);
if (resenc == NULL) resenc = rb_default_external_encoding();
if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
rb_enc_associate(result, resenc);
str_buf_cat2(result, "\"");
p = RSTRING_PTR(str); pend = RSTRING_END(str);
prev = p;
actenc = get_actual_encoding(encidx, str);
if (actenc != enc) {
enc = actenc;
if (unicode_p) unicode_p = rb_enc_unicode_p(enc);
}
while (p < pend) {
unsigned int c, cc;
int n;
n = rb_enc_precise_mbclen(p, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
if (p > prev) str_buf_cat(result, prev, p - prev);
n = rb_enc_mbminlen(enc);
if (pend < p + n)
n = (int)(pend - p);
while (n--) {
snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377);
str_buf_cat(result, buf, strlen(buf));
prev = ++p;
}
continue;
}
n = MBCLEN_CHARFOUND_LEN(n);
c = rb_enc_mbc_to_codepoint(p, pend, enc);
p += n;
if ((asciicompat || unicode_p) &&
(c == '"'|| c == '\\' ||
(c == '#' &&
p < pend &&
MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
(cc = rb_enc_codepoint(p,pend,enc),
(cc == '$' || cc == '@' || cc == '{'))))) {
if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
str_buf_cat2(result, "\\");
if (asciicompat || enc == resenc) {
prev = p - n;
continue;
}
}
switch (c) {
case '\n': cc = 'n'; break;
case '\r': cc = 'r'; break;
case '\t': cc = 't'; break;
case '\f': cc = 'f'; break;
case '\013': cc = 'v'; break;
case '\010': cc = 'b'; break;
case '\007': cc = 'a'; break;
case 033: cc = 'e'; break;
default: cc = 0; break;
}
if (cc) {
if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
buf[0] = '\\';
buf[1] = (char)cc;
str_buf_cat(result, buf, 2);
prev = p;
continue;
}
if ((enc == resenc && rb_enc_isprint(c, enc)) ||
(asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
continue;
}
else {
if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
rb_str_buf_cat_escaped_char(result, c, unicode_p);
prev = p;
continue;
}
}
if (p > prev) str_buf_cat(result, prev, p - prev);
str_buf_cat2(result, "\"");
OBJ_INFECT_RAW(result, str);
return result;
} Возвращает удобочитаемый вид str, заключённый в кавычки, со специальными символами, обработанными экранированием.
str = "hello" str[3] = "\b" str.inspect #=> "\"hel\\bo\""
VALUE
rb_str_intern(VALUE str)
{
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
int type;
#else
ID id;
#endif
VALUE sym = lookup_str_sym(str);
if (sym) {
return sym;
}
#if USE_SYMBOL_GC
enc = rb_enc_get(str);
ascii = rb_usascii_encoding();
if (enc != ascii && sym_check_asciionly(str)) {
str = rb_str_dup(str);
rb_enc_associate(str, ascii);
OBJ_FREEZE(str);
enc = ascii;
}
else {
str = rb_str_new_frozen(str);
}
str = rb_fstring(str);
type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
if (type < 0) type = ID_JUNK;
return dsymbol_alloc(rb_cSymbol, str, enc, type);
#else
id = intern_str(str, 0);
return ID2SYM(id);
#endif
} Возвращает Symbol, соответствующее str, создавая символ, если он ранее не существовал. См. Symbol#id2name.
"Koala".intern #=> :Koala s = 'cat'.to_sym #=> :cat s == :cat #=> true s = '@cat'.to_sym #=> :@cat s == :@cat #=> true
Это также можно использовать для создания символов, которые не могут быть представлены с помощью :xxx обозначения.
'cat and dog'.to_sym #=> :"cat and dog"
VALUE
rb_str_length(VALUE str)
{
return LONG2NUM(str_strlen(str, NULL));
} Возвращает длину строки str в символах.
static VALUE
rb_str_lines(int argc, VALUE *argv, VALUE str)
{
VALUE ary = WANTARRAY("lines", 0);
return rb_str_enumerate_lines(argc, argv, str, ary);
} Возвращает массив строк в str, разделённых с помощью заданного разделителя записей ($/ по умолчанию). Это сокращение для str.each_line(separator, getline_args).to_a.
См. IO.readlines для получения подробной информации о getline_args.
"hello\nworld\n".lines #=> ["hello\n", "world\n"]
"hello world".lines(' ') #=> ["hello ", " ", "world"]
"hello\nworld\n".lines(chomp: true) #=> ["hello", "world"]
Если задан блок, что является устаревшей формой, работает так же, как each_line.
static VALUE
rb_str_ljust(int argc, VALUE *argv, VALUE str)
{
return rb_str_justify(argc, argv, str, 'l');
} Если integer больше длины str, возвращает новую String длиной integer с str, выровненной влево и заполненной padstr; в противном случае возвращает str.
"hello".ljust(4) #=> "hello" "hello".ljust(20) #=> "hello " "hello".ljust(20, '1234') #=> "hello123412341234123"
static VALUE
rb_str_lstrip(VALUE str)
{
char *start;
long len, loffset;
RSTRING_GETMEM(str, start, len);
loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
if (loffset <= 0) return rb_str_dup(str);
return rb_str_subseq(str, loffset, len - loffset);
} Возвращает копию получателя со удалёнными начальными пробелами. См. также String#rstrip и String#strip.
Обратитесь к String#strip для определения пробелов.
" hello ".lstrip #=> "hello " "hello".lstrip #=> "hello"
static VALUE
rb_str_lstrip_bang(VALUE str)
{
rb_encoding *enc;
char *start, *s;
long olen, loffset;
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
loffset = lstrip_offset(str, start, start+olen, enc);
if (loffset > 0) {
long len = olen-loffset;
s = start + loffset;
memmove(start, s, len);
STR_SET_LEN(str, len);
#if !SHARABLE_MIDDLE_SUBSTRING
TERM_FILL(start+len, rb_enc_mbminlen(enc));
#endif
return str;
}
return Qnil;
} Удаляет ведущие пробелы из получателя. Возвращает изменённый получатель или nil, если изменений не было. См. также String#rstrip! и String#strip!.
Обратитесь к String#strip для определения пробелов.
" hello ".lstrip! #=> "hello " "hello ".lstrip! #=> nil "hello".lstrip! #=> nil
static VALUE
rb_str_match_m(int argc, VALUE *argv, VALUE str)
{
VALUE re, result;
if (argc < 1)
rb_check_arity(argc, 1, 2);
re = argv[0];
argv[0] = str;
result = rb_funcallv(get_pat(re), rb_intern("match"), argc, argv);
if (!NIL_P(result) && rb_block_given_p()) {
return rb_yield(result);
}
return result;
} Преобразует pattern в Regexp (если это еще не так), затем вызывает его метод match для str. Если присутствует второй параметр, он указывает позицию в строке, с которой следует начать поиск.
'hello'.match('(.)\1') #=> #<MatchData "ll" 1:"l">
'hello'.match('(.)\1')[0] #=> "ll"
'hello'.match(/(.)\1/)[0] #=> "ll"
'hello'.match(/(.)\1/, 3) #=> nil
'hello'.match('xx') #=> nil
Если задан блок, вызовите блок с MatchData, если совпадение успешно, чтобы вы могли написать
str.match(pat) {|m| ...} вместо
if m = str.match(pat) ... end
В этом случае возвращаемое значение является значением из выполнения блока.
static VALUE
rb_str_match_m_p(int argc, VALUE *argv, VALUE str)
{
VALUE re;
rb_check_arity(argc, 1, 2);
re = get_pat(argv[0]);
return rb_reg_match_p(re, str, argc > 1 ? NUM2LONG(argv[1]) : 0);
} Преобразует pattern в Regexp (если это еще не так), затем возвращает true или false, указывающее, соответствует ли regexp str или нет, без обновления $~ и других связанных переменных. Если присутствует второй параметр, он указывает позицию в строке, с которой следует начать поиск.
"Ruby".match?(/R.../) #=> true "Ruby".match?(/R.../, 1) #=> false "Ruby".match?(/P.../) #=> false $& #=> nil
VALUE
rb_str_succ(VALUE orig)
{
VALUE str;
str = rb_str_new_with_class(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
rb_enc_cr_str_copy_for_substr(str, orig);
OBJ_INFECT(str, orig);
return str_succ(str);
} Возвращает следующий за str элемент. Следующий элемент вычисляется путем инкрементирования символов, начиная с самого правого буквенно-цифрового символа (или самого правого символа, если буквенно-цифровых символов нет) в строке. Инкрементирование цифры всегда приводит к другой цифре, а инкрементирование буквы приводит к другой букве того же регистра. Инкрементирование небуквенно-цифровых символов использует порядковую последовательность базового набора символов.
Если инкремент создает «перенос», инкрементируется символ слева от него. Этот процесс повторяется до тех пор, пока не будет переноса, при необходимости добавляя дополнительный символ.
"abcd".succ #=> "abce" "THX1138".succ #=> "THX1139" "<<koala>>".succ #=> "<<koalb>>" "1999zzz".succ #=> "2000aaa" "ZZZ9999".succ #=> "AAAA0000" "***".succ #=> "**+"
static VALUE
rb_str_succ_bang(VALUE str)
{
rb_str_modify(str);
str_succ(str);
return str;
} Эквивалентно String#succ, но изменяет получатель на месте.
static VALUE
rb_str_oct(VALUE str)
{
return rb_str_to_inum(str, -8, FALSE);
} Рассматривает начальные символы str как строку восьмеричных цифр (с необязательным знаком) и возвращает соответствующее число. Возвращает 0, если преобразование не удалось.
"123".oct #=> 83 "-377".oct #=> -255 "bad".oct #=> 0 "0377bad".oct #=> 255
Если str начинается с 0, учитываются индикаторы основания. См. Kernel#Integer.
VALUE
rb_str_ord(VALUE s)
{
unsigned int c;
c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s));
return UINT2NUM(c);
} Возвращает Integer порядковый номер односимвольной строки.
"a".ord #=> 97
static VALUE
rb_str_partition(VALUE str, VALUE sep)
{
long pos;
sep = get_pat_quoted(sep, 0);
if (RB_TYPE_P(sep, T_REGEXP)) {
pos = rb_reg_search(sep, str, 0, 0);
if (pos < 0) {
failed:
return rb_ary_new3(3, rb_str_dup(str), str_new_empty(str), str_new_empty(str));
}
sep = rb_str_subpat(str, sep, INT2FIX(0));
if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed;
}
else {
pos = rb_str_index(str, sep, 0);
if (pos < 0) goto failed;
}
return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
sep,
rb_str_subseq(str, pos+RSTRING_LEN(sep),
RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
} Ищет sep или шаблон (regexp) в строке и возвращает часть перед ним, совпадение и часть после него. Если он не найден, возвращает две пустые строки и str.
"hello".partition("l") #=> ["he", "l", "lo"]
"hello".partition("x") #=> ["hello", "", ""]
"hello".partition(/.l/) #=> ["h", "el", "lo"]
static VALUE
rb_str_prepend_multi(int argc, VALUE *argv, VALUE str)
{
str_modifiable(str);
if (argc == 1) {
rb_str_update(str, 0L, 0L, argv[0]);
}
else if (argc > 1) {
int i;
VALUE arg_str = rb_str_tmp_new(0);
rb_enc_copy(arg_str, str);
for (i = 0; i < argc; i++) {
rb_str_append(arg_str, argv[i]);
}
rb_str_update(str, 0L, 0L, arg_str);
}
return str;
} Добавление в начало — Добавляет заданные строки в начало str.
a = "!"
a.prepend("hello ", "world") #=> "hello world!"
a #=> "hello world!"
См. также String#concat.
VALUE
rb_str_replace(VALUE str, VALUE str2)
{
str_modifiable(str);
if (str == str2) return str;
StringValue(str2);
str_discard(str);
return str_replace(str, str2);
} Заменяет содержимое и зараженность str соответствующими значениями в other_str.
s = "hello" #=> "hello" s.replace "world" #=> "world"
static VALUE
rb_str_reverse(VALUE str)
{
rb_encoding *enc;
VALUE rev;
char *s, *e, *p;
int cr;
if (RSTRING_LEN(str) <= 1) return rb_str_dup(str);
enc = STR_ENC_GET(str);
rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
s = RSTRING_PTR(str); e = RSTRING_END(str);
p = RSTRING_END(rev);
cr = ENC_CODERANGE(str);
if (RSTRING_LEN(str) > 1) {
if (single_byte_optimizable(str)) {
while (s < e) {
*--p = *s++;
}
}
else if (cr == ENC_CODERANGE_VALID) {
while (s < e) {
int clen = rb_enc_fast_mbclen(s, e, enc);
p -= clen;
memcpy(p, s, clen);
s += clen;
}
}
else {
cr = rb_enc_asciicompat(enc) ?
ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
while (s < e) {
int clen = rb_enc_mbclen(s, e, enc);
if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN;
p -= clen;
memcpy(p, s, clen);
s += clen;
}
}
}
STR_SET_LEN(rev, RSTRING_LEN(str));
OBJ_INFECT_RAW(rev, str);
str_enc_copy(rev, str);
ENC_CODERANGE_SET(rev, cr);
return rev;
} Возвращает новую строку с символами из str в обратном порядке.
"stressed".reverse #=> "desserts"
static VALUE
rb_str_reverse_bang(VALUE str)
{
if (RSTRING_LEN(str) > 1) {
if (single_byte_optimizable(str)) {
char *s, *e, c;
str_modify_keep_cr(str);
s = RSTRING_PTR(str);
e = RSTRING_END(str) - 1;
while (s < e) {
c = *s;
*s++ = *e;
*e-- = c;
}
}
else {
str_shared_replace(str, rb_str_reverse(str));
}
}
else {
str_modify_keep_cr(str);
}
return str;
} Разворачивает str на месте.
static VALUE
rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE vpos;
rb_encoding *enc = STR_ENC_GET(str);
long pos, len = str_strlen(str, enc); /* str's enc */
if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
pos = NUM2LONG(vpos);
if (pos < 0) {
pos += len;
if (pos < 0) {
if (RB_TYPE_P(sub, T_REGEXP)) {
rb_backref_set(Qnil);
}
return Qnil;
}
}
if (pos > len) pos = len;
}
else {
pos = len;
}
if (SPECIAL_CONST_P(sub)) goto generic;
switch (BUILTIN_TYPE(sub)) {
case T_REGEXP:
/* enc = rb_get_check(str, sub); */
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
enc, single_byte_optimizable(str));
pos = rb_reg_search(sub, str, pos, 1);
pos = rb_str_sublen(str, pos);
if (pos >= 0) return LONG2NUM(pos);
break;
generic:
default: {
VALUE tmp;
tmp = rb_check_string_type(sub);
if (NIL_P(tmp)) {
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_obj_classname(sub));
}
sub = tmp;
}
/* fall through */
case T_STRING:
pos = rb_str_rindex(str, sub, pos);
if (pos >= 0) return LONG2NUM(pos);
break;
}
return Qnil;
} Возвращает индекс последнего вхождения данной подстроки или шаблона (regexp) в str. Возвращает nil, если не найдено. Если присутствует второй параметр, он указывает позицию в строке, чтобы завершить поиск — символы за этой точкой не будут рассматриваться.
"hello".rindex('e') #=> 1
"hello".rindex('l') #=> 3
"hello".rindex('a') #=> nil
"hello".rindex(?e) #=> 1
"hello".rindex(/[aeiou]/, -2) #=> 1
static VALUE
rb_str_rjust(int argc, VALUE *argv, VALUE str)
{
return rb_str_justify(argc, argv, str, 'r');
} Если integer больше длины str, возвращает новую String длиной integer с str, выровненной справа и дополненной padstr; в противном случае возвращает str.
"hello".rjust(4) #=> "hello" "hello".rjust(20) #=> " hello" "hello".rjust(20, '1234') #=> "123412341234123hello"
static VALUE
rb_str_rpartition(VALUE str, VALUE sep)
{
long pos = RSTRING_LEN(str);
int regex = FALSE;
if (RB_TYPE_P(sep, T_REGEXP)) {
pos = rb_reg_search(sep, str, pos, 1);
regex = TRUE;
}
else {
VALUE tmp;
tmp = rb_check_string_type(sep);
if (NIL_P(tmp)) {
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_obj_classname(sep));
}
sep = tmp;
pos = rb_str_sublen(str, pos);
pos = rb_str_rindex(str, sep, pos);
}
if (pos < 0) {
return rb_ary_new3(3, str_new_empty(str), str_new_empty(str), rb_str_dup(str));
}
if (regex) {
sep = rb_reg_nth_match(0, rb_backref_get());
}
else {
pos = rb_str_offset(str, pos);
}
return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
sep,
rb_str_subseq(str, pos+RSTRING_LEN(sep),
RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
} Ищет sep или шаблон (regexp) в строке с конца строки и возвращает часть перед ним, совпадение и часть после него. Если он не найден, возвращает две пустые строки и str.
"hello".rpartition("l") #=> ["hel", "l", "o"]
"hello".rpartition("x") #=> ["", "", "hello"]
"hello".rpartition(/.l/) #=> ["he", "ll", "o"]
static VALUE
rb_str_rstrip(VALUE str)
{
rb_encoding *enc;
char *start;
long olen, roffset;
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
roffset = rstrip_offset(str, start, start+olen, enc);
if (roffset <= 0) return rb_str_dup(str);
return rb_str_subseq(str, 0, olen-roffset);
} Возвращает копию получателя с удаленными завершающими пробелами. См. также String#lstrip и String#strip.
Обратитесь к String#strip за определением пробелов.
" hello ".rstrip #=> " hello" "hello".rstrip #=> "hello"
static VALUE
rb_str_rstrip_bang(VALUE str)
{
rb_encoding *enc;
char *start;
long olen, roffset;
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
roffset = rstrip_offset(str, start, start+olen, enc);
if (roffset > 0) {
long len = olen - roffset;
STR_SET_LEN(str, len);
#if !SHARABLE_MIDDLE_SUBSTRING
TERM_FILL(start+len, rb_enc_mbminlen(enc));
#endif
return str;
}
return Qnil;
} Удаляет завершающие пробелы из получателя. Возвращает измененный получатель или nil, если изменений не было. См. также String#lstrip! и String#strip!.
Обратитесь к String#strip за определением пробелов.
" hello ".rstrip! #=> " hello" " hello".rstrip! #=> nil "hello".rstrip! #=> nil
static VALUE
rb_str_scan(VALUE str, VALUE pat)
{
VALUE result;
long start = 0;
long last = -1, prev = 0;
char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str);
pat = get_pat_quoted(pat, 1);
mustnot_broken(str);
if (!rb_block_given_p()) {
VALUE ary = rb_ary_new();
while (!NIL_P(result = scan_once(str, pat, &start, 0))) {
last = prev;
prev = start;
rb_ary_push(ary, result);
}
if (last >= 0) rb_pat_search(pat, str, last, 1);
else rb_backref_set(Qnil);
return ary;
}
while (!NIL_P(result = scan_once(str, pat, &start, 1))) {
last = prev;
prev = start;
rb_yield(result);
str_mod_check(str, p, len);
}
if (last >= 0) rb_pat_search(pat, str, last, 1);
return str;
} Обе формы итеративно обрабатывают str, сопоставляя шаблон (который может быть Regexp или String). Для каждого совпадения создается результат, который либо добавляется в результирующий массив, либо передается в блок. Если шаблон не содержит групп, каждый отдельный результат состоит из совпадающей строки, $&. Если шаблон содержит группы, каждый отдельный результат сам по себе является массивом, содержащим по одной записи на группу.
a = "cruel world" a.scan(/\w+/) #=> ["cruel", "world"] a.scan(/.../) #=> ["cru", "el ", "wor"] a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
И форма с блоком:
a.scan(/\w+/) {|w| print "<<#{w}>> " }
print "\n"
a.scan(/(.)(.)/) {|x,y| print y, x }
print "\n"
дает:
<<cruel>> <<world>> rceu lowlr
# File lib/scanf.rb, line 720
def scanf(fstr,&b) #:yield: current_match
if b
block_scanf(fstr,&b)
else
fs =
if fstr.is_a? Scanf::FormatString
fstr
else
Scanf::FormatString.new(fstr)
end
fs.match(self)
end
end Сканирует текущую строку. Если задан блок, он работает точно так же, как block_scanf.
arr = "123 456".scanf("%d%d")
# => [123, 456]
require 'pp'
"this 123 read that 456 other".scanf("%s%d%s") {|m| pp m}
# ["this", 123, "read"]
# ["that", 456, "other"]
# => [["this", 123, "read"], ["that", 456, "other"]]
См. Scanf для получения подробной информации о создании строки формата.
Вам необходимо загрузить модуль 'scanf', чтобы использовать String#scanf
static VALUE
str_scrub(int argc, VALUE *argv, VALUE str)
{
VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
VALUE new = rb_str_scrub(str, repl);
return NIL_P(new) ? rb_str_dup(str): new;
} Если строка является недопустимой последовательностью байтов, то заменяет недопустимые байты заданным символом замены, иначе возвращает self. Если задан блок, заменяет недопустимые байты возвращаемым значением блока.
"abc\u3042\x81".scrub #=> "abc\u3042\uFFFD"
"abc\u3042\x81".scrub("*") #=> "abc\u3042*"
"abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
static VALUE
str_scrub_bang(int argc, VALUE *argv, VALUE str)
{
VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
VALUE new = rb_str_scrub(str, repl);
if (!NIL_P(new)) rb_str_replace(str, new);
return str;
} Если строка является недопустимой последовательностью байтов, то заменяет недопустимые байты заданным символом замены, иначе возвращает self. Если задан блок, заменяет недопустимые байты возвращаемым значением блока.
"abc\u3042\x81".scrub! #=> "abc\u3042\uFFFD"
"abc\u3042\x81".scrub!("*") #=> "abc\u3042*"
"abc\u3042\xE3\x80".scrub!{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
static VALUE
rb_str_setbyte(VALUE str, VALUE index, VALUE value)
{
long pos = NUM2LONG(index);
long len = RSTRING_LEN(str);
char *head, *left = 0;
unsigned char *ptr;
rb_encoding *enc;
int cr = ENC_CODERANGE_UNKNOWN, width, nlen;
if (pos < -len || len <= pos)
rb_raise(rb_eIndexError, "index %ld out of string", pos);
if (pos < 0)
pos += len;
VALUE v = rb_to_int(value);
VALUE w = rb_int_modulo(v, INT2FIX(256));
unsigned char byte = NUM2INT(w) & 0xFF;
if (!str_independent(str))
str_make_independent(str);
enc = STR_ENC_GET(str);
head = RSTRING_PTR(str);
ptr = (unsigned char *)&head[pos];
if (!STR_EMBED_P(str)) {
cr = ENC_CODERANGE(str);
switch (cr) {
case ENC_CODERANGE_7BIT:
left = (char *)ptr;
*ptr = byte;
if (ISASCII(byte)) goto end;
nlen = rb_enc_precise_mbclen(left, head+len, enc);
if (!MBCLEN_CHARFOUND_P(nlen))
ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
else
ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
goto end;
case ENC_CODERANGE_VALID:
left = rb_enc_left_char_head(head, ptr, head+len, enc);
width = rb_enc_precise_mbclen(left, head+len, enc);
*ptr = byte;
nlen = rb_enc_precise_mbclen(left, head+len, enc);
if (!MBCLEN_CHARFOUND_P(nlen))
ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
else if (MBCLEN_CHARFOUND_LEN(nlen) != width || ISASCII(byte))
ENC_CODERANGE_CLEAR(str);
goto end;
}
}
ENC_CODERANGE_CLEAR(str);
*ptr = byte;
end:
return value;
} модифицирует index-й байт как integer.
# File lib/shellwords.rb, line 215 def shellescape Shellwords.escape(self) end
Экранирует str таким образом, чтобы он безопасно использовался в командной строке оболочки Bourne.
См. Shellwords.shellescape для получения подробной информации.
# File lib/shellwords.rb, line 204 def shellsplit Shellwords.split(self) end
Разделяет str на массив токенов таким же образом, как это делает оболочка UNIX Bourne.
См. Shellwords.shellsplit для получения подробной информации.
VALUE
rb_str_length(VALUE str)
{
return LONG2NUM(str_strlen(str, NULL));
} Возвращает длину строки str в символах.
static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
return rb_str_subpat(str, argv[0], argv[1]);
}
else {
long beg = NUM2LONG(argv[0]);
long len = NUM2LONG(argv[1]);
return rb_str_substr(str, beg, len);
}
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0]);
} Ссылка на элемент — Если передано одно index, возвращает подстроку длиной в один символ по указанному индексу. Если переданы start индекс и length, возвращает подстроку, содержащую length символов, начиная с start индекса. Если передано range, его начало и конец интерпретируются как смещения, ограничивающие подстроку, которая должна быть возвращена.
В этих трёх случаях, если индекс отрицательный, он считается с конца строки. Для start и range случаев начальный индекс находится перед символом, а индекс, соответствующий размеру строки. Кроме того, пустая строка возвращается, когда начальный индекс для диапазона символов находится в конце строки.
Возвращает nil если начальный индекс выходит за пределы строки или длина отрицательная.
Если предоставлен Regexp, возвращается соответствующая часть строки. Если за регулярным выражением следует capture, который может быть индексом или именем группы захвата, за регулярным выражением возвращается соответствующая часть объекта MatchData.
Если задана match_str, возвращается эта строка, если она встречается в строке.
Возвращает nil если регулярное выражение не соответствует или совпадающая строка не найдена.
a = "hello there" a[1] #=> "e" a[2, 3] #=> "llo" a[2..3] #=> "ll" a[-3, 2] #=> "er" a[7..-2] #=> "her" a[-4..-2] #=> "her" a[-2..-4] #=> "" a[11, 0] #=> "" a[11] #=> nil a[12, 0] #=> nil a[12..-1] #=> nil a[/[aeiou](.)\1/] #=> "ell" a[/[aeiou](.)\1/, 0] #=> "ell" a[/[aeiou](.)\1/, 1] #=> "l" a[/[aeiou](.)\1/, 2] #=> nil a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l" a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"] #=> "e" a["lo"] #=> "lo" a["bye"] #=> nil
static VALUE
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
{
VALUE result;
VALUE buf[3];
int i;
rb_check_arity(argc, 1, 2);
for (i=0; i<argc; i++) {
buf[i] = argv[i];
}
str_modify_keep_cr(str);
result = rb_str_aref_m(argc, buf, str);
if (!NIL_P(result)) {
buf[i] = rb_str_new(0,0);
rb_str_aset_m(argc+1, buf, str);
}
return result;
} Удаляет указанную часть из str и возвращает удалённую часть.
string = "this is a string"
string.slice!(2) #=> "i"
string.slice!(3..6) #=> " is "
string.slice!(/s.*t/) #=> "sa st"
string.slice!("r") #=> "r"
string #=> "thing"
static VALUE
rb_str_split_m(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
VALUE spat;
VALUE limit;
enum {awk, string, regexp} split_type;
long beg, end, i = 0, empty_count = -1;
int lim = 0;
VALUE result, tmp;
result = rb_block_given_p() ? Qfalse : Qnil;
if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
lim = NUM2INT(limit);
if (lim <= 0) limit = Qnil;
else if (lim == 1) {
if (RSTRING_LEN(str) == 0)
return result ? rb_ary_new2(0) : str;
tmp = rb_str_dup(str);
if (!result) {
rb_yield(tmp);
return str;
}
return rb_ary_new3(1, tmp);
}
i = 1;
}
if (NIL_P(limit) && !lim) empty_count = 0;
enc = STR_ENC_GET(str);
split_type = regexp;
if (!NIL_P(spat)) {
spat = get_pat_quoted(spat, 0);
}
else if (NIL_P(spat = rb_fs)) {
split_type = awk;
}
else if (!(spat = rb_fs_check(spat))) {
rb_raise(rb_eTypeError, "value of $; must be String or Regexp");
}
if (split_type != awk) {
if (BUILTIN_TYPE(spat) == T_STRING) {
rb_encoding *enc2 = STR_ENC_GET(spat);
mustnot_broken(spat);
split_type = string;
if (RSTRING_LEN(spat) == 0) {
/* Special case - split into chars */
spat = rb_reg_regcomp(spat);
split_type = regexp;
}
else if (rb_enc_asciicompat(enc2) == 1) {
if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
split_type = awk;
}
}
else {
int l;
if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' &&
RSTRING_LEN(spat) == l) {
split_type = awk;
}
}
}
}
#define SPLIT_STR(beg, len) (empty_count = split_string(result, str, beg, len, empty_count))
if (result) result = rb_ary_new();
beg = 0;
if (split_type == awk) {
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
char *bptr = ptr;
int skip = 1;
unsigned int c;
end = beg;
if (is_ascii_string(str)) {
while (ptr < eptr) {
c = (unsigned char)*ptr++;
if (skip) {
if (ascii_isspace(c)) {
beg = ptr - bptr;
}
else {
end = ptr - bptr;
skip = 0;
if (!NIL_P(limit) && lim <= i) break;
}
}
else if (ascii_isspace(c)) {
SPLIT_STR(beg, end-beg);
skip = 1;
beg = ptr - bptr;
if (!NIL_P(limit)) ++i;
}
else {
end = ptr - bptr;
}
}
}
else {
while (ptr < eptr) {
int n;
c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
ptr += n;
if (skip) {
if (rb_isspace(c)) {
beg = ptr - bptr;
}
else {
end = ptr - bptr;
skip = 0;
if (!NIL_P(limit) && lim <= i) break;
}
}
else if (rb_isspace(c)) {
SPLIT_STR(beg, end-beg);
skip = 1;
beg = ptr - bptr;
if (!NIL_P(limit)) ++i;
}
else {
end = ptr - bptr;
}
}
}
}
else if (split_type == string) {
char *ptr = RSTRING_PTR(str);
char *str_start = ptr;
char *substr_start = ptr;
char *eptr = RSTRING_END(str);
char *sptr = RSTRING_PTR(spat);
long slen = RSTRING_LEN(spat);
mustnot_broken(str);
enc = rb_enc_check(str, spat);
while (ptr < eptr &&
(end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
/* Check we are at the start of a char */
char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
if (t != ptr + end) {
ptr = t;
continue;
}
SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
ptr += end + slen;
substr_start = ptr;
if (!NIL_P(limit) && lim <= ++i) break;
}
beg = ptr - str_start;
}
else {
char *ptr = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
long start = beg;
long idx;
int last_null = 0;
struct re_registers *regs;
while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
regs = RMATCH_REGS(rb_backref_get());
if (start == end && BEG(0) == END(0)) {
if (!ptr) {
SPLIT_STR(0, 0);
break;
}
else if (last_null == 1) {
SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, ptr+len, enc));
beg = start;
}
else {
if (start == len)
start++;
else
start += rb_enc_fast_mbclen(ptr+start,ptr+len,enc);
last_null = 1;
continue;
}
}
else {
SPLIT_STR(beg, end-beg);
beg = start = END(0);
}
last_null = 0;
for (idx=1; idx < regs->num_regs; idx++) {
if (BEG(idx) == -1) continue;
SPLIT_STR(BEG(idx), END(idx)-BEG(idx));
}
if (!NIL_P(limit) && lim <= ++i) break;
}
}
if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
SPLIT_STR(beg, RSTRING_LEN(str)-beg);
}
return result ? result : str;
} Делит str на подстроки на основе разделителя, возвращая массив этих подстрок.
Если pattern является String, его содержимое используется в качестве разделителя при разделении str. Если pattern - это одиночный пробел, str разделяется по пробелам, с игнорированием начальных и конечных пробелов, а также последовательностей пробелов.
Если pattern является Regexp, str разделяется там, где совпадает шаблон. Всякий раз, когда шаблон соответствует нулевой строке, str разделяется на отдельные символы. Если pattern содержит группы, соответствующие совпадения будут возвращены в массиве также.
Если pattern равен nil, используется значение $;. Если $; равен nil (по умолчанию), str разделяется по пробелам, как если бы был указан ' '.
Если параметр limit опущен, отбрасываются конечные нулевые поля. Если limit является положительным числом, возвращается не более этого количества разделенных подстрок (захваченные группы также возвращаются, но не учитываются в лимите). Если limit равен 1, вся строка возвращается как единственный элемент массива. Если отрицательный, нет ограничений на количество возвращаемых полей, и конечные нулевые поля не отбрасываются.
Когда входная str пустая, возвращается пустой Array, так как строка считается не имеющей полей для разделения.
" now's the time ".split #=> ["now's", "the", "time"]
" now's the time ".split(' ') #=> ["now's", "the", "time"]
" now's the time".split(/ /) #=> ["", "now's", "", "the", "time"]
"1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
"hello".split(//) #=> ["h", "e", "l", "l", "o"]
"hello".split(//, 3) #=> ["h", "e", "llo"]
"hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"]
"mellow yellow".split("ello") #=> ["m", "w y", "w"]
"1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"]
"1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"]
"1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""]
"1:2:3".split(/(:)()()/, 2) #=> ["1", ":", "", "", "2:3"]
"".split(',', -1) #=> []
Если задан блок, вызывается блок с каждой подстрокой.
static VALUE
rb_str_squeeze(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_squeeze_bang(argc, argv, str);
return str;
} Создает набор символов из параметра(ов) other_str, используя процедуру, описанную для String#count. Возвращает новую строку, где последовательности одинаковых символов, которые присутствуют в этом наборе, заменяются на один символ. Если аргументы не указаны, все последовательности одинаковых символов заменяются одним символом.
"yellow moon".squeeze #=> "yelow mon"
" now is the".squeeze(" ") #=> " now is the"
"putters shoot balls".squeeze("m-z") #=> "puters shot balls"
static VALUE
rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
{
char squeez[TR_TABLE_SIZE];
rb_encoding *enc = 0;
VALUE del = 0, nodel = 0;
unsigned char *s, *send, *t;
int i, modify = 0;
int ascompat, singlebyte = single_byte_optimizable(str);
unsigned int save;
if (argc == 0) {
enc = STR_ENC_GET(str);
}
else {
for (i=0; i<argc; i++) {
VALUE s = argv[i];
StringValue(s);
enc = rb_enc_check(str, s);
if (singlebyte && !single_byte_optimizable(s))
singlebyte = 0;
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
}
str_modify_keep_cr(str);
s = t = (unsigned char *)RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
send = (unsigned char *)RSTRING_END(str);
save = -1;
ascompat = rb_enc_asciicompat(enc);
if (singlebyte) {
while (s < send) {
unsigned int c = *s++;
if (c != save || (argc > 0 && !squeez[c])) {
*t++ = save = c;
}
}
}
else {
while (s < send) {
unsigned int c;
int clen;
if (ascompat && (c = *s) < 0x80) {
if (c != save || (argc > 0 && !squeez[c])) {
*t++ = save = c;
}
s++;
}
else {
c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, enc);
if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
if (t != s) rb_enc_mbcput(c, t, enc);
save = c;
t += clen;
}
s += clen;
}
}
}
TERM_FILL((char *)t, TERM_LEN(str));
if ((char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
STR_SET_LEN(str, (char *)t - RSTRING_PTR(str));
modify = 1;
}
if (modify) return str;
return Qnil;
} Сжимает str на месте, возвращая либо str, либо nil если изменений не было.
static VALUE
rb_str_start_with(int argc, VALUE *argv, VALUE str)
{
int i;
for (i=0; i<argc; i++) {
VALUE tmp = argv[i];
if (RB_TYPE_P(tmp, T_REGEXP)) {
if (rb_reg_start_with_p(tmp, str))
return Qtrue;
}
else {
StringValue(tmp);
rb_enc_check(str, tmp);
if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
return Qtrue;
}
}
return Qfalse;
} Возвращает true, если str начинается с одного из prefixes заданных. Каждый из prefixes должен быть String или Regexp.
"hello".start_with?("hell") #=> true
"hello".start_with?(/H/i) #=> true
# returns true if one of the prefixes matches.
"hello".start_with?("heaven", "hell") #=> true
"hello".start_with?("heaven", "paradise") #=> false
static VALUE
rb_str_strip(VALUE str)
{
char *start;
long olen, loffset, roffset;
rb_encoding *enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
loffset = lstrip_offset(str, start, start+olen, enc);
roffset = rstrip_offset(str, start+loffset, start+olen, enc);
if (loffset <= 0 && roffset <= 0) return rb_str_dup(str);
return rb_str_subseq(str, loffset, olen-loffset-roffset);
} Возвращает копию получателя с удалёнными начальными и конечными пробелами.
Пробелы определяются как любой из следующих символов: null, горизонтальная табуляция, перевод строки, вертикальная табуляция, форма подачи, возврат каретки, пробел.
" hello ".strip #=> "hello" "\tgoodbye\r\n".strip #=> "goodbye" "\x00\t\n\v\f\r ".strip #=> "" "hello".strip #=> "hello"
static VALUE
rb_str_strip_bang(VALUE str)
{
char *start;
long olen, loffset, roffset;
rb_encoding *enc;
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
loffset = lstrip_offset(str, start, start+olen, enc);
roffset = rstrip_offset(str, start+loffset, start+olen, enc);
if (loffset > 0 || roffset > 0) {
long len = olen-roffset;
if (loffset > 0) {
len -= loffset;
memmove(start, start + loffset, len);
}
STR_SET_LEN(str, len);
#if !SHARABLE_MIDDLE_SUBSTRING
TERM_FILL(start+len, rb_enc_mbminlen(enc));
#endif
return str;
}
return Qnil;
} Удаляет начальные и конечные пробелы из получателя. Возвращает изменённый получатель или nil, если изменений не было.
Обратитесь к String#strip для определения пробелов.
" hello ".strip! #=> "hello" "hello".strip! #=> nil
static VALUE
rb_str_sub(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_sub_bang(argc, argv, str);
return str;
} Возвращает копию str с первым вхождением pattern заменённым вторым аргументом. Второй аргумент обычно является Regexp; если он указан как String, все метасимволы регулярных выражений в нём будут интерпретироваться буквально, например, '\\d' будет соответствовать обратной косой черте, за которой следует 'd', а не цифре.
Если второй аргумент является String, он будет заменён на совпавший текст. Он может содержать обратные ссылки на группы захвата шаблона в формате "\d", где d - номер группы, или "\k<n>", где n - имя группы. Если это строка в двойных кавычках, обе обратные ссылки должны предваряться дополнительной обратной косой чертой. Однако, внутри replacement специальные переменные соответствия, такие как $&, не будут ссылаться на текущее соответствие. Если replacement является String, которая выглядит как группа захвата шаблона, но на самом деле ею не является, например, "\'", то она должна предваряться двумя обратными косыми чертами, как в "\\'".
Если второй аргумент является Hash, и совпавший текст является одним из его ключей, соответствующее значение является строкой замены.
В форме с блоком текущая строка соответствия передаётся в качестве параметра, и переменные, такие как $1, $2, $`, $&, и $' будут установлены соответствующим образом. Возвращаемое значение блока будет подставлено вместо совпадения при каждом вызове.
Результат наследует любые метки в исходной строке или любой предоставленной строке замены.
"hello".sub(/[aeiou]/, '*') #=> "h*llo"
"hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo"
"hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello"
"hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo"
'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
#=> "Is /bin/bash your preferred shell?"
static VALUE
rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
{
VALUE pat, repl, hash = Qnil;
int iter = 0;
int tainted = 0;
long plen;
int min_arity = rb_block_given_p() ? 1 : 2;
long beg;
rb_check_arity(argc, min_arity, 2);
if (argc == 1) {
iter = 1;
}
else {
repl = argv[1];
hash = rb_check_hash_type(argv[1]);
if (NIL_P(hash)) {
StringValue(repl);
}
tainted = OBJ_TAINTED_RAW(repl);
}
pat = get_pat_quoted(argv[0], 1);
str_modifiable(str);
beg = rb_pat_search(pat, str, 0, 1);
if (beg >= 0) {
rb_encoding *enc;
int cr = ENC_CODERANGE(str);
long beg0, end0;
VALUE match, match0 = Qnil;
struct re_registers *regs;
char *p, *rp;
long len, rlen;
match = rb_backref_get();
regs = RMATCH_REGS(match);
if (RB_TYPE_P(pat, T_STRING)) {
beg0 = beg;
end0 = beg0 + RSTRING_LEN(pat);
match0 = pat;
}
else {
beg0 = BEG(0);
end0 = END(0);
if (iter) match0 = rb_reg_nth_match(0, match);
}
if (iter || !NIL_P(hash)) {
p = RSTRING_PTR(str); len = RSTRING_LEN(str);
if (iter) {
repl = rb_obj_as_string(rb_yield(match0));
}
else {
repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
repl = rb_obj_as_string(repl);
}
str_mod_check(str, p, len);
rb_check_frozen(str);
}
else {
repl = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
}
enc = rb_enc_compatible(str, repl);
if (!enc) {
rb_encoding *str_enc = STR_ENC_GET(str);
p = RSTRING_PTR(str); len = RSTRING_LEN(str);
if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
rb_enc_name(str_enc),
rb_enc_name(STR_ENC_GET(repl)));
}
enc = STR_ENC_GET(repl);
}
rb_str_modify(str);
rb_enc_associate(str, enc);
tainted |= OBJ_TAINTED_RAW(repl);
if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
int cr2 = ENC_CODERANGE(repl);
if (cr2 == ENC_CODERANGE_BROKEN ||
(cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
cr = ENC_CODERANGE_UNKNOWN;
else
cr = cr2;
}
plen = end0 - beg0;
rp = RSTRING_PTR(repl); rlen = RSTRING_LEN(repl);
len = RSTRING_LEN(str);
if (rlen > plen) {
RESIZE_CAPA(str, len + rlen - plen);
}
p = RSTRING_PTR(str);
if (rlen != plen) {
memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
}
memcpy(p + beg0, rp, rlen);
len += rlen - plen;
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
ENC_CODERANGE_SET(str, cr);
FL_SET_RAW(str, tainted);
return str;
}
return Qnil;
} Выполняет ту же подстановку, что и String#sub, непосредственно.
Возвращает str если подстановка была выполнена или nil если подстановка не была выполнена.
VALUE
rb_str_succ(VALUE orig)
{
VALUE str;
str = rb_str_new_with_class(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
rb_enc_cr_str_copy_for_substr(str, orig);
OBJ_INFECT(str, orig);
return str_succ(str);
} Возвращает преемника str. Преемник вычисляется путём инкрементирования символов, начиная с самого правого буквенно-цифрового символа (или последнего символа, если буквенно-цифровых символов нет) в строке. Инкрементирование цифры всегда приводит к другой цифре, а инкрементирование буквы приводит к другой букве той же регистровой формы. Инкрементирование небуквенно-цифровых символов использует порядок сортировки на основе набора символов.
Если инкрементирование приводит к переносу, символ слева от него увеличивается. Этот процесс повторяется до тех пор, пока не произойдёт перенос, добавляя дополнительный символ при необходимости.
"abcd".succ #=> "abce" "THX1138".succ #=> "THX1139" "<<koala>>".succ #=> "<<koalb>>" "1999zzz".succ #=> "2000aaa" "ZZZ9999".succ #=> "AAAA0000" "***".succ #=> "**+"
static VALUE
rb_str_succ_bang(VALUE str)
{
rb_str_modify(str);
str_succ(str);
return str;
} Эквивалентно String#succ, но изменяет получателя непосредственно.
static VALUE
rb_str_sum(int argc, VALUE *argv, VALUE str)
{
int bits = 16;
char *ptr, *p, *pend;
long len;
VALUE sum = INT2FIX(0);
unsigned long sum0 = 0;
if (rb_check_arity(argc, 0, 1) && (bits = NUM2INT(argv[0])) < 0) {
bits = 0;
}
ptr = p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
pend = p + len;
while (p < pend) {
if (FIXNUM_MAX - UCHAR_MAX < sum0) {
sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
str_mod_check(str, ptr, len);
sum0 = 0;
}
sum0 += (unsigned char)*p;
p++;
}
if (bits == 0) {
if (sum0) {
sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
}
}
else {
if (sum == INT2FIX(0)) {
if (bits < (int)sizeof(long)*CHAR_BIT) {
sum0 &= (((unsigned long)1)<<bits)-1;
}
sum = LONG2FIX(sum0);
}
else {
VALUE mod;
if (sum0) {
sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
}
mod = rb_funcall(INT2FIX(1), idLTLT, 1, INT2FIX(bits));
mod = rb_funcall(mod, '-', 1, INT2FIX(1));
sum = rb_funcall(sum, '&', 1, mod);
}
}
return sum;
} Возвращает базовую контрольную сумму n-битов символов в str, где n - необязательный параметр Integer, по умолчанию равный 16. Результат - просто сумма двоичного значения каждого байта в str по модулю 2**n - 1. Это не очень хорошая контрольная сумма.
static VALUE
rb_str_swapcase(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_swapcase_bang(argc, argv, str);
return str;
} Возвращает копию str с заглавными буквенными символами, преобразованными в строчные, и строчными символами, преобразованными в заглавные.
См. String#downcase для значения options и использования с различными кодировками.
"Hello".swapcase #=> "hELLO" "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"
static VALUE
rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Эквивалентно String#swapcase, но изменяет получателя непосредственно, возвращая str или nil если изменений не было.
См. String#downcase для значения options и использования с различными кодировками.
static VALUE
rb_str_to_f(VALUE str)
{
return DBL2NUM(rb_str_to_dbl(str, FALSE));
} Возвращает результат интерпретации начальных символов в str как число с плавающей точкой. Избыточные символы после конца корректного числа игнорируются. Если в начале str нет корректного числа, возвращается 0.0. Этот метод никогда не генерирует исключение.
"123.45e1".to_f #=> 1234.5 "45.67 degrees".to_f #=> 45.67 "thx1138".to_f #=> 0.0
static VALUE
rb_str_to_i(int argc, VALUE *argv, VALUE str)
{
int base = 10;
if (rb_check_arity(argc, 0, 1) && (base = NUM2INT(argv[0])) < 0) {
rb_raise(rb_eArgError, "invalid radix %d", base);
}
return rb_str_to_inum(str, base, FALSE);
} Возвращает результат интерпретации начальных символов в str как целое число в системе счисления base (от 2 до 36). Избыточные символы после конца корректного числа игнорируются. Если в начале str нет корректного числа, возвращается 0. Этот метод никогда не генерирует исключение, когда base корректен.
"12345".to_i #=> 12345 "99 red balloons".to_i #=> 99 "0a".to_i #=> 0 "0a".to_i(16) #=> 10 "hello".to_i #=> 0 "1100101".to_i(2) #=> 101 "1100101".to_i(8) #=> 294977 "1100101".to_i(10) #=> 1100101 "1100101".to_i(16) #=> 17826049
static VALUE
string_to_r(VALUE self)
{
VALUE num;
rb_must_asciicompat(self);
num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
rb_raise(rb_eFloatDomainError, "Infinity");
return num;
} Возвращает результат интерпретации начальных символов в str как рациональное число. Начальные пробелы и избыточные символы после конца корректного числа игнорируются. Последовательности цифр могут быть разделены нижним подчеркиванием. Если в начале str нет корректного числа, возвращается ноль. Этот метод никогда не генерирует исключение.
' 2 '.to_r #=> (2/1) '300/2'.to_r #=> (150/1) '-9.2'.to_r #=> (-46/5) '-9.2e2'.to_r #=> (-920/1) '1_234_567'.to_r #=> (1234567/1) '21 June 09'.to_r #=> (21/1) '21/06/09'.to_r #=> (7/2) 'BWV 1079'.to_r #=> (0/1)
ПРИМЕЧАНИЕ: “0.3”.to_r не то же самое, что 0.3.to_r. Первый эквивалентен “3/10”.to_r, но второй нет.
"0.3".to_r == 3/10r #=> true 0.3.to_r == 3/10r #=> false
См. также Kernel#Rational.
VALUE
rb_str_intern(VALUE str)
{
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
int type;
#else
ID id;
#endif
VALUE sym = lookup_str_sym(str);
if (sym) {
return sym;
}
#if USE_SYMBOL_GC
enc = rb_enc_get(str);
ascii = rb_usascii_encoding();
if (enc != ascii && sym_check_asciionly(str)) {
str = rb_str_dup(str);
rb_enc_associate(str, ascii);
OBJ_FREEZE(str);
enc = ascii;
}
else {
str = rb_str_new_frozen(str);
}
str = rb_fstring(str);
type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
if (type < 0) type = ID_JUNK;
return dsymbol_alloc(rb_cSymbol, str, enc, type);
#else
id = intern_str(str, 0);
return ID2SYM(id);
#endif
} Возвращает Symbol соответствующий str, создавая символ, если он ранее не существовал. См. Symbol#id2name.
"Koala".intern #=> :Koala s = 'cat'.to_sym #=> :cat s == :cat #=> true s = '@cat'.to_sym #=> :@cat s == :@cat #=> true
Это также можно использовать для создания символов, которые нельзя представить с помощью :xxx обозначения.
'cat and dog'.to_sym #=> :"cat and dog"
static VALUE
rb_str_tr(VALUE str, VALUE src, VALUE repl)
{
str = rb_str_dup(str);
tr_trans(str, src, repl, 0);
return str;
} Возвращает копию str с символами из from_str заменёнными соответствующими символами из to_str. Если to_str короче from_str, оно дополняется последним символом, чтобы сохранить соответствие.
"hello".tr('el', 'ip') #=> "hippo"
"hello".tr('aeiou', '*') #=> "h*ll*"
"hello".tr('aeiou', 'AA*') #=> "hAll*"
Обе строки могут использовать c1-c2 обозначение для обозначения диапазонов символов, и from_str может начинаться с ^, что обозначает все символы, кроме указанных.
"hello".tr('a-y', 'b-z') #=> "ifmmp"
"hello".tr('^aeiou', '*') #=> "*e**o"
Символ обратной косой черты \ может использоваться для экранирования ^ или - и в противном случае игнорируется, если он не появляется в конце диапазона или в конце from_str или to_str:
"hello^world".tr("\\^aeiou", "*") #=> "h*ll**w*rld"
"hello-world".tr("a\\-eo", "*") #=> "h*ll**w*rld"
"hello\r\nworld".tr("\r", "") #=> "hello\nworld"
"hello\r\nworld".tr("\\r", "") #=> "hello\r\nwold"
"hello\r\nworld".tr("\\\r", "") #=> "hello\nworld"
"X['\\b']".tr("X\\", "") #=> "['b']"
"X['\\b']".tr("X-\\]", "") #=> "'b'"
static VALUE
rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
{
return tr_trans(str, src, repl, 0);
} Производит замену символов в str на месте, используя те же правила, что и String#tr. Возвращает str или nil если изменений не было.
static VALUE
rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
{
str = rb_str_dup(str);
tr_trans(str, src, repl, 1);
return str;
} Обрабатывает копию str, как описано в String#tr, затем удаляет повторяющиеся символы в регионах, которые были затронуты переводом.
"hello".tr_s('l', 'r') #=> "hero"
"hello".tr_s('el', '*') #=> "h*o"
"hello".tr_s('el', 'hx') #=> "hhxo"
static VALUE
rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
{
return tr_trans(str, src, repl, 1);
} Выполняет обработку String#tr_s над str на месте, возвращая str или nil если изменений не было.
static VALUE
str_undump(VALUE str)
{
const char *s = RSTRING_PTR(str);
const char *s_end = RSTRING_END(str);
rb_encoding *enc = rb_enc_get(str);
VALUE undumped = rb_enc_str_new(s, 0L, enc);
bool utf8 = false;
bool binary = false;
int w;
rb_must_asciicompat(str);
if (rb_str_is_ascii_only_p(str) == Qfalse) {
rb_raise(rb_eRuntimeError, "non-ASCII character detected");
}
if (!str_null_check(str, &w)) {
rb_raise(rb_eRuntimeError, "string contains null byte");
}
if (RSTRING_LEN(str) < 2) goto invalid_format;
if (*s != '"') goto invalid_format;
/* strip '"' at the start */
s++;
for (;;) {
if (s >= s_end) {
rb_raise(rb_eRuntimeError, "unterminated dumped string");
}
if (*s == '"') {
/* epilogue */
s++;
if (s == s_end) {
/* ascii compatible dumped string */
break;
}
else {
static const char force_encoding_suffix[] = ".force_encoding(\""; /* "\")" */
static const char dup_suffix[] = ".dup";
const char *encname;
int encidx;
ptrdiff_t size;
/* check separately for strings dumped by older versions */
size = sizeof(dup_suffix) - 1;
if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
size = sizeof(force_encoding_suffix) - 1;
if (s_end - s <= size) goto invalid_format;
if (memcmp(s, force_encoding_suffix, size) != 0) goto invalid_format;
s += size;
if (utf8) {
rb_raise(rb_eRuntimeError, "dumped string contained Unicode escape but used force_encoding");
}
encname = s;
s = memchr(s, '"', s_end-s);
size = s - encname;
if (!s) goto invalid_format;
if (s_end - s != 2) goto invalid_format;
if (s[0] != '"' || s[1] != ')') goto invalid_format;
encidx = rb_enc_find_index2(encname, (long)size);
if (encidx < 0) {
rb_raise(rb_eRuntimeError, "dumped string has unknown encoding name");
}
rb_enc_associate_index(undumped, encidx);
}
break;
}
if (*s == '\\') {
s++;
if (s >= s_end) {
rb_raise(rb_eRuntimeError, "invalid escape");
}
undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
}
else {
rb_str_cat(undumped, s++, 1);
}
}
OBJ_INFECT(undumped, str);
return undumped;
invalid_format:
rb_raise(rb_eRuntimeError, "invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
} Создаёт незаэкранированную версию str. См. также String#dump, так как String#undump делает обратное преобразование по отношению к String#dump.
"\"hello \\n ''\"".undump #=> "hello \n ''"
static VALUE
rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
{
return unicode_normalize_common(argc, argv, str, id_normalize);
} Нормализация Unicode — Возвращает нормализованную форму str, используя нормализации Unicode NFC, NFD, NFKC или NFKD. Используемая форма нормализации определяется form, которая может принимать любое из четырёх значений :nfc, :nfd, :nfkc, или :nfkd. По умолчанию используется :nfc.
Если строка не в кодировке Unicode Encoding, то генерируется исключение Exception. В данном контексте «кодировка Unicode» означает любую из UTF-8, UTF-16BE/LE и UTF-32BE/LE, а также GB18030, UCS_2BE и UCS_4BE. Любая кодировка, отличная от UTF-8, реализуется путем преобразования в UTF-8, что делает её медленнее, чем UTF-8.
"a\u0300".unicode_normalize #=> "\u00E0"
"a\u0300".unicode_normalize(:nfc) #=> "\u00E0"
"\u00E0".unicode_normalize(:nfd) #=> "a\u0300"
"\xE0".force_encoding('ISO-8859-1').unicode_normalize(:nfd)
#=> Encoding::CompatibilityError raised
static VALUE
rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
{
return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
} Деструктивная версия String#unicode_normalize, выполняющая нормализацию Unicode на месте.
static VALUE
rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
{
return unicode_normalize_common(argc, argv, str, id_normalized_p);
} Проверяет, находится ли str в форме нормализации Unicode form, которая может принимать любое из четырёх значений :nfc, :nfd, :nfkc, или :nfkd. По умолчанию используется :nfc.
Если строка не в кодировке Unicode Encoding, то генерируется исключение Exception. Для подробностей см. String#unicode_normalize.
"a\u0300".unicode_normalized? #=> false
"a\u0300".unicode_normalized?(:nfd) #=> true
"\u00E0".unicode_normalized? #=> true
"\u00E0".unicode_normalized?(:nfd) #=> false
"\xE0".force_encoding('ISO-8859-1').unicode_normalized?
#=> Encoding::CompatibilityError raised
static VALUE
pack_unpack(VALUE str, VALUE fmt)
{
int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY;
return pack_unpack_internal(str, fmt, mode);
} Декодирует str (который может содержать двоичные данные) в соответствии со строкой формата, возвращая массив из каждого извлеченного значения. Строка формата состоит из последовательности символов-директивы, подытоженных в таблице в конце этого раздела. Каждая директива может быть после нее числом, указывающим количество повторений с этой директивой. Звездочка («*») использует все оставшиеся элементы. Директивы sSiIlL могут быть за ними знак подчеркивания («_») или знак восклицания («!»), чтобы использовать базовый размер платформы для указанного типа; в противном случае используется независимый от платформы согласованный размер. Пробелы в строке формата игнорируются. См. также String#unpack1, Array#pack.
"abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
"abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
"abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
"aa".unpack('b8B8') #=> ["10000110", "01100001"]
"aaa".unpack('h2H2c') #=> ["16", "61", 97]
"\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
"now=20is".unpack('M*') #=> ["now is"]
"whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
В этой таблице подытоживаются различные форматы и классы Ruby, возвращаемые каждым из них.
Integer | |
Directive | Returns | Meaning
------------------------------------------------------------------
C | Integer | 8-bit unsigned (unsigned char)
S | Integer | 16-bit unsigned, native endian (uint16_t)
L | Integer | 32-bit unsigned, native endian (uint32_t)
Q | Integer | 64-bit unsigned, native endian (uint64_t)
J | Integer | pointer width unsigned, native endian (uintptr_t)
| |
c | Integer | 8-bit signed (signed char)
s | Integer | 16-bit signed, native endian (int16_t)
l | Integer | 32-bit signed, native endian (int32_t)
q | Integer | 64-bit signed, native endian (int64_t)
j | Integer | pointer width signed, native endian (intptr_t)
| |
S_ S! | Integer | unsigned short, native endian
I I_ I! | Integer | unsigned int, native endian
L_ L! | Integer | unsigned long, native endian
Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
| | if the platform has no long long type.)
J! | Integer | uintptr_t, native endian (same with J)
| |
s_ s! | Integer | signed short, native endian
i i_ i! | Integer | signed int, native endian
l_ l! | Integer | signed long, native endian
q_ q! | Integer | signed long long, native endian (ArgumentError
| | if the platform has no long long type.)
j! | Integer | intptr_t, native endian (same with j)
| |
S> s> S!> s!> | Integer | same as the directives without ">" except
L> l> L!> l!> | | big endian
I!> i!> | |
Q> q> Q!> q!> | | "S>" is same as "n"
J> j> J!> j!> | | "L>" is same as "N"
| |
S< s< S!< s!< | Integer | same as the directives without "<" except
L< l< L!< l!< | | little endian
I!< i!< | |
Q< q< Q!< q!< | | "S<" is same as "v"
J< j< J!< j!< | | "L<" is same as "V"
| |
n | Integer | 16-bit unsigned, network (big-endian) byte order
N | Integer | 32-bit unsigned, network (big-endian) byte order
v | Integer | 16-bit unsigned, VAX (little-endian) byte order
V | Integer | 32-bit unsigned, VAX (little-endian) byte order
| |
U | Integer | UTF-8 character
w | Integer | BER-compressed integer (see Array.pack)
Float | |
Directive | Returns | Meaning
-----------------------------------------------------------------
D d | Float | double-precision, native format
F f | Float | single-precision, native format
E | Float | double-precision, little-endian byte order
e | Float | single-precision, little-endian byte order
G | Float | double-precision, network (big-endian) byte order
g | Float | single-precision, network (big-endian) byte order
String | |
Directive | Returns | Meaning
-----------------------------------------------------------------
A | String | arbitrary binary string (remove trailing nulls and ASCII spaces)
a | String | arbitrary binary string
Z | String | null-terminated string
B | String | bit string (MSB first)
b | String | bit string (LSB first)
H | String | hex string (high nibble first)
h | String | hex string (low nibble first)
u | String | UU-encoded string
M | String | quoted-printable, MIME encoding (see RFC2045)
m | String | base64 encoded string (RFC 2045) (default)
| | base64 encoded string (RFC 4648) if followed by 0
P | String | pointer to a structure (fixed-length string)
p | String | pointer to a null-terminated string
Misc. | |
Directive | Returns | Meaning
-----------------------------------------------------------------
@ | --- | skip to the offset given by the length argument
X | --- | skip backward one byte
x | --- | skip forward one byte ИСТОРИЯ
-
J, J! j, и j! доступны начиная с Ruby 2.3.
-
Q_, Q!, q_, и q! доступны начиная с Ruby 2.1.
-
I!<, i!<, I!>, и i!> доступны начиная с Ruby 1.9.3.
static VALUE
pack_unpack1(VALUE str, VALUE fmt)
{
return pack_unpack_internal(str, fmt, UNPACK_1);
} Декодирует str (который может содержать двоичные данные) в соответствии со строкой формата, возвращая первое извлечённое значение. См. также String#unpack, Array#pack.
static VALUE
rb_str_upcase(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_upcase_bang(argc, argv, str);
return str;
} Возвращает копию str со всеми строчными буквами, заменёнными соответствующими заглавными буквами.
См. String#downcase для смысла options и использования с разными кодировками.
"hEllO".upcase #=> "HELLO"
static VALUE
rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (((flags&ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() || rb_enc_mbmaxlen(enc)==1))
|| (!(flags&ONIGENC_CASE_FOLD_TURKISH_AZERI) && ENC_CODERANGE(str)==ENC_CODERANGE_7BIT)) {
char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
while (s < send) {
unsigned int c = *(unsigned char*)s;
if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
*s = 'A' + (c - 'a');
flags |= ONIGENC_CASE_MODIFIED;
}
s++;
}
}
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Преобразует содержимое str в заглавные буквы, возвращая nil если изменений не было.
См. String#downcase для смысла options и использования с разными кодировками.
static VALUE
rb_str_upto(int argc, VALUE *argv, VALUE beg)
{
VALUE end, exclusive;
rb_scan_args(argc, argv, "11", &end, &exclusive);
RETURN_ENUMERATOR(beg, argc, argv);
return rb_str_upto_each(beg, end, RTEST(exclusive), str_upto_i, Qnil);
} Итерируется по последовательным значениям, начиная с str и заканчивая other_str включительно, передавая каждое значение в блок. Метод String#succ используется для генерации каждого значения. Если необязательный второй аргумент exclusive опущен или равен false, последнее значение будет включено; в противном случае оно будет исключено.
Если блок не задан, вместо него возвращается перечислитель.
"a8".upto("b6") {|s| print s, ' ' }
for s in "a8".."b6"
print s, ' '
end
выводит:
a8 a9 b0 b1 b2 b3 b4 b5 b6 a8 a9 b0 b1 b2 b3 b4 b5 b6
Если str и other_str содержат только символы арабских цифр, оба распознаются как десятичные числа. Кроме того, ширина строки (например, ведущие нули) обрабатывается должным образом.
"9".upto("11").to_a #=> ["9", "10", "11"]
"25".upto("5").to_a #=> []
"07".upto("11").to_a #=> ["07", "08", "09", "10", "11"]
static VALUE
rb_str_valid_encoding_p(VALUE str)
{
int cr = rb_enc_str_coderange(str);
return cr == ENC_CODERANGE_BROKEN ? Qfalse : Qtrue;
} Возвращает true для строки, которая закодирована правильно.
"\xc2\xa1".force_encoding("UTF-8").valid_encoding? #=> true
"\xc2".force_encoding("UTF-8").valid_encoding? #=> false
"\x80".force_encoding("UTF-8").valid_encoding? #=> false
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.