класс String
Объект String хранит и обрабатывает произвольную последовательность байтов, обычно представляющую символы. Объекты String могут быть созданы с помощью String::new или в виде литералов.
Из-за проблем с алиасингом пользователи строк должны быть осведомлены о методах, которые изменяют содержимое объекта String. Как правило, методы с именами, оканчивающимися на «!», изменяют свой получатель, в то время как методы без «!'' возвращают новый String. Однако существуют исключения, такие как String#[]=.
Публичные методы класса
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 */
char *new_ptr = ALLOC_N(char, (size_t)capa + termlen);
memcpy(new_ptr, RSTRING(str)->as.ary, RSTRING_EMBED_LEN_MAX + 1);
RSTRING(str)->as.heap.ptr = new_ptr;
}
else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
const size_t size = (size_t)capa + termlen;
const char *const old_ptr = RSTRING_PTR(str);
const size_t osize = RSTRING(str)->as.heap.len + TERM_LEN(str);
char *new_ptr = ALLOC_N(char, (size_t)capa + termlen);
memcpy(new_ptr, old_ptr, osize < size ? osize : size);
FL_UNSET_RAW(str, STR_SHARED);
RSTRING(str)->as.heap.ptr = new_ptr;
}
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);
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);
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);
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);
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)
{
if (!BARE_STRING_P(str) && !rb_obj_frozen_p(str)) {
str = rb_str_dup(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 rb_str_eql_internal(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 rb_str_eql_internal(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);
ENC_CODERANGE_CLEAR(str2);
return str2;
} Возвращает скопированную строку, кодировка которой ASCII-8BIT.
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)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
VALUE ret;
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str;
if (flags&ONIGENC_CASE_ASCII_ONLY) {
ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
ret = rb_str_casemap(str, &flags, enc);
}
return ret;
} Возвращает копию 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_true_enc(str);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, 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();
return result;
} Возвращает строку, сгенерированную при вызове стандартной функции crypt(3) библиотеки с str и salt_str, в указанном порядке, в качестве аргументов. Пожалуйста, больше не используйте этот метод. Он устарел; предоставляется только для обратной совместимости со скриптами ruby более ранних дней. Его не следует использовать в современных программах по нескольким причинам:
-
Поведение функции C
crypt(3)зависит от операционной системы, на которой она выполняется. Сгенерированная строка не обладает переносимостью данных. -
В некоторых ОС, таких как Mac OS,
crypt(3)никогда не завершается ошибкой (т.е. в итоге приводит к непредсказуемым результатам). -
В некоторых ОС, таких как Mac OS,
crypt(3)не является потокобезопасной. -
Так называемое «традиционное» использование
crypt(3)очень слабо. Согласно его странице справки, традиционный вывод функцииcrypt(3)Linux имеет только 2**56 вариантов; слишком легко взломать сегодня. И это поведение по умолчанию. -
Для повышения надёжности некоторые ОС реализуют так называемое «модульное» использование. Для этого необходимо вручную выполнить сложную настройку параметра
salt_str. Ошибки при генерации правильной строки соли обычно не приводят к ошибкам; опечатки в параметрах обычно не обнаруживаются.-
Например, во втором вызове
String#cryptв примере ниже есть ошибка; в «round=” отсутствует «s». Однако вызов не приводит к ошибке и генерируется что-то непредсказуемое."foo".crypt("$5$rounds=1000$salt$") # OK, proper usage "foo".crypt("$5$round=1000$salt$") # Typo not detected
-
-
Даже в «модульном» режиме некоторые хеш-функции считаются устаревшими и больше не рекомендуются; например, модуль
$1$официально покинул разработку автором: см. phk.freebsd.dk/sagas/md5crypt_eol.html. Для другого примера, модуль$3$считается полностью неисправным: см. справку FreeBSD. -
В некоторых ОС, таких как Mac OS, нет модульного режима. Однако, как написано выше,
crypt(3)в Mac OS никогда не завершается ошибкой. Это означает, что даже если вы создадите правильную строку соли, она всё равно сгенерирует традиционный DES-хеш, и вы не сможете этого обнаружить."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)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
VALUE ret;
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
if (case_option_single_p(flags, enc, str)) {
ret = rb_str_new_with_class(str, RSTRING_PTR(str), RSTRING_LEN(str));
str_enc_copy(ret, str);
downcase_single(ret);
}
else if (flags&ONIGENC_CASE_ASCII_ONLY) {
ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
ret = rb_str_casemap(str, &flags, enc);
}
return ret;
} Возвращает копию 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_true_enc(str);
if (case_option_single_p(flags, enc, str)) {
if (downcase_single(str))
flags |= ONIGENC_CASE_MODIFIED;
}
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, 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();
}
/* result from dump is ASCII */
rb_enc_associate_index(result, encidx);
ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT);
return result;
} Возвращает цитированную версию строки, в которой все непечатаемые символы заменены на обозначение \xHH и все специальные символы экранированы.
Этот метод может быть использован для обратного преобразования: если полученный new_str будет обработан с помощью eval, он вернёт исходную строку.
"hello \n ''".dump #=> "\"hello \\n ''\"" "\f\x00\xff\\\"".dump #=> "\"\\f\\x00\\xFF\\\\\\\"\""
См. также String#undump.
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 при работе со строками Unicode, в переданный блок. Для кодировок, отличных от 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, эта функция перебирает графемные кластеры, определяемые спецификацией Unicode Standard Annex #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 с использованием заданного разделителя строк (по умолчанию $/) и передаёт каждую подстроку в переданный блок. Если задан разделитель нулевой длины, строка разбивается на абзацы, ограниченные несколькими последовательными символами новой строки.
Если chomp имеет значение true, separator будет удалён из конца каждой строки.
Если блок не задан, вместо него возвращается итератор.
"hello\nworld".each_line {|s| p s}
# prints:
# "hello\n"
# "world"
"hello\nworld".each_line('l') {|s| p s}
# prints:
# "hel"
# "l"
# "o\nworl"
# "d"
"hello\n\n\nworld".each_line('') {|s| p s}
# prints
# "hello\n\n"
# "world"
"hello\nworld".each_line(chomp: true) {|s| p s}
# prints:
# "hello"
# "world"
"hello\nworld".each_line('l', chomp: true) {|s| p s}
# prints:
# "he"
# ""
# "o\nwor"
# "d"
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” для форм кодировки Unicode и “?” в противном случае.
- :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, который представляет кодировку obj.
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 rb_str_eql_internal(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 — имя группы. Аналогично, \&, \', \`, и + соответствуют специальным переменным $&, $', $`, и $+, соответственно. (Подробности см. в regexp.rdoc.) \0 то же, что и \&. \\ интерпретируется как экранирование, то есть одиночная обратная косая черта. Обратите внимание, что внутри replacement специальные переменные соответствия, такие как $&, не будут ссылаться на текущее соответствие.
Если второй аргумент — Hash, и совпавший текст является одним из его ключей, соответствующее значение будет строкой замены.
В форме с блоком текущая строка соответствия передаётся в качестве параметра, и такие переменные, как $1, $2, $`, $&, и $' будут установлены соответствующим образом. (Подробности см. в regexp.rdoc.) Значение, возвращаемое блоком, будет подставлено вместо совпадения при каждом вызове.
Если не задан ни блок, ни второй аргумент, возвращается 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*"
Обратите внимание, что строковая литерал потребляет обратные косые черты. (Подробности о строковых литералах см. в syntax/literals.rdoc). Обратные ссылки обычно предваряются дополнительной обратной косой чертой. Например, если вы хотите написать обратную ссылку \& в replacement со строковой литералом с двойными кавычками, вам нужно написать: "..\\&..". Если вы хотите написать строку без обратной ссылки \& в replacement, вам нужно сначала экранировать обратную косую черту, чтобы предотвратить интерпретацию её как обратной ссылки, а затем нужно экранировать обратные косые черты ещё раз, чтобы предотвратить потребление их строковой литералом: "..\\\\&..". Чтобы избежать большого количества обратных косых черт, можно использовать форму с блоком.
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);
} Возвращает индекс первого вхождения заданной подстроки или шаблона (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, "\"");
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_dup(str);
OBJ_FREEZE(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"
# File ext/nkf/lib/kconv.rb, line 264 def iseuc; Kconv.iseuc(self) end
Возвращает, является ли кодировка self EUC-JP или нет.
# File ext/nkf/lib/kconv.rb, line 276 def isjis; Kconv.isjis(self) end
Возвращает, является ли кодировка self ISO-2022-JP или нет.
# File ext/nkf/lib/kconv.rb, line 270 def issjis; Kconv.issjis(self) end
Возвращает, является ли кодировка self Shift_JIS или нет.
# File ext/nkf/lib/kconv.rb, line 282 def isutf8; Kconv.isutf8(self) end
Возвращает значение self, кодировка UTF-8 или нет.
# 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.
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.
Если chomp равно true, separator будет удалено с конца каждой строки.
"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, возвращает новую строку длиной 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 (если это не 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 (если это не Regexp), затем возвращает значение true или false, указывающее, соответствует ли регулярное выражение 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);
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);
} Возвращает порядковый номер символа строки из одного символа.
"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));
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
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_and(v, INT2FIX(0xff));
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, chars} 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");
}
else {
rb_warn("$; is set to non-nil value");
}
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 */
split_type = chars;
}
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;
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
if (split_type == awk) {
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 *str_start = ptr;
char *substr_start = ptr;
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 if (split_type == chars) {
char *str_start = ptr;
int n;
mustnot_broken(str);
enc = rb_enc_get(str);
while (ptr < eptr &&
(n = rb_enc_precise_mbclen(ptr, eptr, enc)) > 0) {
SPLIT_STR(ptr - str_start, n);
ptr += n;
if (!NIL_P(limit) && lim <= ++i) break;
}
beg = ptr - str_start;
}
else {
long len = RSTRING_LEN(str);
long start = beg;
long idx;
int last_null = 0;
struct re_registers *regs;
VALUE match = 0;
for (; (end = rb_reg_search(spat, str, start, 0)) >= 0;
(match ? (rb_match_unbusy(match), rb_backref_set(match)) : (void)0)) {
match = rb_backref_get();
if (!result) rb_match_busy(match);
regs = RMATCH_REGS(match);
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, eptr, enc));
beg = start;
}
else {
if (start == len)
start++;
else
start += rb_enc_fast_mbclen(ptr+start,eptr,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 (match) rb_match_unbusy(match);
}
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);
} Возвращает копию получателя со удалёнными начальными и конечными пробелами.
Пробелы определяются как любой из следующих символов: нуль, горизонтальная табуляция, перевод строки, вертикальная табуляция, разделитель страницы, возврат каретки, пробел.
" 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 — имя группы. Аналогично, \&, \', \`, и + соответствуют специальным переменным, $&, $', $`, и $+, соответственно. (См. regexp.rdoc для подробностей). \0 то же, что и \&. \\ интерпретируется как escape, т.е. как одиночная обратная косая черта. Обратите внимание, что внутри replacement специальные переменные соответствия, такие как $&, не будут ссылаться на текущее соответствие.
Если второй аргумент является Hash, а совпавший текст — одним из его ключей, соответствующее значение будет строкой замены.
В форме блока текущая строка соответствия передаётся в качестве параметра, и переменные, такие как $1, $2, $`, $&, и $' будут установлены соответствующим образом. (См. regexp.rdoc для подробностей). Значение, возвращаемое блоком, будет заменено на совпадение в каждом вызове.
"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?"
Обратите внимание, что строковая константа потребляет обратные косые черты. (См. syntax/literals.rdoc для получения подробностей о строковых константах). Ссылки на обратные ссылки обычно предваряются дополнительной обратной косой чертой. Например, если вы хотите написать ссылку на обратную ссылку \& в replacement со строковой константой в двойных кавычках, вам нужно написать: "..\\&..". Если вы хотите написать строку без обратной ссылки \& в replacement, вам сначала нужно экранировать обратную косую черту, чтобы предотвратить интерпретацию её этим методом как ссылки на обратную ссылку, а затем вам нужно снова экранировать обратные косые черты, чтобы предотвратить потребление их строковой константой: "..\\\\&..". Вы можете использовать форму блока, чтобы избежать множества обратных косых черт.
static VALUE
rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
{
VALUE pat, repl, hash = Qnil;
int iter = 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);
}
}
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);
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;
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);
}
rp = RSTRING_PTR(repl);
memmove(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);
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);
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)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
VALUE ret;
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str;
if (flags&ONIGENC_CASE_ASCII_ONLY) {
ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
ret = rb_str_casemap(str, &flags, enc);
}
return ret;
} Возвращает копию 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_true_enc(str);
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, 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
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/bigdecimal/lib/bigdecimal/util.rb, line 68 def to_d BigDecimal.interpret_loosely(self) end
Возвращает результат интерпретации начальных символов в str как BigDecimal.
require 'bigdecimal' require 'bigdecimal/util' "0.5".to_d # => 0.5e0 "123.45e1".to_d # => 0.12345e4 "45.67 degrees".to_d # => 0.4567e2
См. также BigDecimal::new.
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_dup(str);
OBJ_FREEZE(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"
# 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
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);
}
}
return undumped;
invalid_format:
rb_raise(rb_eRuntimeError, "invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
} Возвращает неэкранированную версию строки. Это обратная операция к 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
# File pack.rb, line 256 def unpack(fmt) __builtin_pack_unpack(fmt) end
Декодирует 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.
# File pack.rb, line 280 def unpack1(fmt) __builtin_pack_unpack1(fmt) end
Декодирует str (который может содержать двоичные данные) согласно строке формата, возвращая первое извлечённое значение. См. также String#unpack, Array#pack.
Разница с String#unpack:
"abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
"abc \0\0abc \0\0".unpack1('A6Z6') #=> "abc"
В этом случае данные будут потеряны, но часто случается, что массив содержит только одно значение, особенно при разборе двоичных данных. Например:
“xffx00x00x00”.unpack(“l”) #=> [255] “xffx00x00x00”.unpack1(“l”) #=> 255
Таким образом, unpack1 удобен, чётко отражает намерение и сигнализирует ожидаемое возвращаемое значение для тех, кто читает код.
static VALUE
rb_str_upcase(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
VALUE ret;
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
if (case_option_single_p(flags, enc, str)) {
ret = rb_str_new_with_class(str, RSTRING_PTR(str), RSTRING_LEN(str));
str_enc_copy(ret, str);
upcase_single(ret);
}
else if (flags&ONIGENC_CASE_ASCII_ONLY) {
ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
ret = rb_str_casemap(str, &flags, enc);
}
return ret;
} Возвращает копию 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_true_enc(str);
if (case_option_single_p(flags, enc, str)) {
if (upcase_single(str))
flags |= ONIGENC_CASE_MODIFIED;
}
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, 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.