класс String
Объект String хранит и обрабатывает произвольную последовательность байтов, обычно представляющую символы. Объекты String могут быть созданы с помощью String::new или в качестве литералов.
Из-за проблем с алиасированием пользователи строк должны быть осведомлены о методах, которые изменяют содержимое объекта String. Обычно методы с названиями, оканчивающимися на «!», изменяют свой получатель, а те, у которых нет «!», возвращают новый объект String. Однако есть исключения, такие как String#[]=.
Методы экземпляра публичного интерфейса
# File ext/nkf/lib/kconv.rb, line 263 def iseuc; Kconv.iseuc(self) end
Возвращает, является ли кодировка объекта self EUC-JP или нет.
# File ext/nkf/lib/kconv.rb, line 275 def isjis; Kconv.isjis(self) end
Возвращает, является ли кодировка объекта self ISO-2022-JP или нет.
# File ext/nkf/lib/kconv.rb, line 269 def issjis; Kconv.issjis(self) end
Возвращает, является ли кодировка объекта self Shift_JIS или нет.
# File ext/nkf/lib/kconv.rb, line 281 def isutf8; Kconv.isutf8(self) end
Возвращает, является ли кодировка объекта self UTF-8 или нет.
# File ext/nkf/lib/kconv.rb, line 204 def kconv(to_enc, from_enc=nil) from_enc = self.encoding if !from_enc && self.encoding != Encoding.list[0] Kconv::kconv(self, to_enc, from_enc) end
Преобразует self в to_enc. to_enc и from_enc задаются как константы объектов Kconv или Encoding.
static VALUE
string_to_c(VALUE self)
{
char *s;
VALUE num;
rb_must_asciicompat(self);
s = RSTRING_PTR(self);
if (s && s[RSTRING_LEN(self)]) {
rb_str_modify(self);
s = RSTRING_PTR(self);
s[RSTRING_LEN(self)] = '\0';
}
if (!s)
s = (char *)"";
(void)parse_comp(s, 0, &num);
return num;
} Возвращает комплексное число, обозначающее строковую форму. Парсер игнорирует ведущие пробелы и хвостовой мусор. Любые числовые последовательности могут быть разделены подчеркиванием. Возвращает ноль для нулевой или мусорной строки.
'9'.to_c #=> (9+0i) '2.5'.to_c #=> (2.5+0i) '2.5/1'.to_c #=> ((5/2)+0i) '-3/2'.to_c #=> ((-3/2)+0i) '-i'.to_c #=> (0-1i) '45i'.to_c #=> (0+45i) '3-4i'.to_c #=> (3-4i) '-4e2-4e-2i'.to_c #=> (-400.0-0.04i) '-0.0-0.0i'.to_c #=> (-0.0-0.0i) '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i) 'ruby'.to_c #=> (0+0i)
См. Kernel.Complex.
# File ext/bigdecimal/lib/bigdecimal/util.rb, line 66
def to_d
begin
BigDecimal(self)
rescue ArgumentError
BigDecimal(0)
end
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.
# File ext/nkf/lib/kconv.rb, line 223 def toeuc; Kconv.toeuc(self) end
Преобразует self в EUC-JP.
scanf
↑ верхМетоды класса публичного интерфейса
static VALUE
rb_str_init(int argc, VALUE *argv, VALUE str)
{
static ID keyword_ids[2];
VALUE orig, opt, venc, vcapa;
VALUE kwargs[2];
rb_encoding *enc = 0;
int n;
if (!keyword_ids[0]) {
keyword_ids[0] = rb_id_encoding();
CONST_ID(keyword_ids[1], "capacity");
}
n = rb_scan_args(argc, argv, "01:", &orig, &opt);
if (!NIL_P(opt)) {
rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
venc = kwargs[0];
vcapa = kwargs[1];
if (venc != Qundef && !NIL_P(venc)) {
enc = rb_to_encoding(venc);
}
if (vcapa != Qundef && !NIL_P(vcapa)) {
long capa = NUM2LONG(vcapa);
long len = 0;
int termlen = enc ? rb_enc_mbminlen(enc) : 1;
if (capa < STR_BUF_MIN_SIZE) {
capa = STR_BUF_MIN_SIZE;
}
if (n == 1) {
StringValue(orig);
len = RSTRING_LEN(orig);
if (capa < len) {
capa = len;
}
if (orig == str) n = 0;
}
str_modifiable(str);
if (STR_EMBED_P(str)) { /* make noembed always */
RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)capa + termlen);
}
else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
REALLOC_N(RSTRING(str)->as.heap.ptr, char, (size_t)capa + termlen);
}
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_format_m(VALUE str, VALUE arg)
{
VALUE tmp = rb_check_array_type(arg);
if (!NIL_P(tmp)) {
VALUE rv = rb_str_format(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp), str);
RB_GC_GUARD(tmp);
return rv;
}
return rb_str_format(1, &arg, str);
} Форматирование—Использует str в качестве спецификации формата и возвращает результат её применения к arg. Если спецификация формата содержит более одной подстановки, то arg должен быть Array или Hash, содержащим значения для подстановки. Подробности строки формата см. в Kernel::sprintf.
"%05d" % 123 #=> "00123"
"%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6"
"foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"
VALUE
rb_str_times(VALUE str, VALUE times)
{
VALUE str2;
long n, len;
char *ptr2;
int termlen;
if (times == INT2FIX(1)) {
return rb_str_dup(str);
}
if (times == INT2FIX(0)) {
str2 = str_alloc(rb_obj_class(str));
rb_enc_copy(str2, str);
OBJ_INFECT(str2, str);
return str2;
}
len = NUM2LONG(times);
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
str2 = str_alloc(rb_obj_class(str));
if (!STR_EMBEDDABLE_P(len, 1)) {
RSTRING(str2)->as.heap.aux.capa = len;
RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
STR_SET_NOEMBED(str2);
}
STR_SET_LEN(str2, len);
rb_enc_copy(str2, str);
OBJ_INFECT(str2, str);
return str2;
}
if (len && LONG_MAX/len < RSTRING_LEN(str)) {
rb_raise(rb_eArgError, "argument too big");
}
len *= RSTRING_LEN(str);
termlen = TERM_LEN(str);
str2 = str_new0(rb_obj_class(str), 0, len, termlen);
ptr2 = RSTRING_PTR(str2);
if (len) {
n = RSTRING_LEN(str);
memcpy(ptr2, RSTRING_PTR(str), n);
while (n <= len/2) {
memcpy(ptr2 + n, ptr2, n);
n *= 2;
}
memcpy(ptr2 + n, ptr2, len-n);
}
STR_SET_LEN(str2, len);
TERM_FILL(&ptr2[len], termlen);
OBJ_INFECT(str2, str);
rb_enc_cr_str_copy_for_substr(str2, str);
return str2;
} Копирование—Возвращает новую строку, содержащую integer копий получателя. integer должно быть больше или равно 0.
"Ho! " * 3 #=> "Ho! Ho! Ho! " "Ho! " * 0 #=> ""
VALUE
rb_str_plus(VALUE str1, VALUE str2)
{
VALUE str3;
rb_encoding *enc;
char *ptr1, *ptr2, *ptr3;
long len1, len2;
int termlen;
StringValue(str2);
enc = rb_enc_check_str(str1, str2);
RSTRING_GETMEM(str1, ptr1, len1);
RSTRING_GETMEM(str2, ptr2, len2);
termlen = rb_enc_mbminlen(enc);
if (len1 > LONG_MAX - len2) {
rb_raise(rb_eArgError, "string size too big");
}
str3 = str_new0(rb_cString, 0, len1+len2, termlen);
ptr3 = RSTRING_PTR(str3);
memcpy(ptr3, ptr1, len1);
memcpy(ptr3+len1, ptr2, len2);
TERM_FILL(&ptr3[len1+len2], termlen);
FL_SET_RAW(str3, OBJ_TAINTED_RAW(str1) | OBJ_TAINTED_RAW(str2));
ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
RB_GC_GUARD(str1);
RB_GC_GUARD(str2);
return str3;
} Конкатенация—Возвращает новую String, содержащую other_str, конкатенированную со строкой str.
"Hello from " + self.to_s #=> "Hello from main"
static VALUE
str_uplus(VALUE str)
{
if (OBJ_FROZEN(str)) {
return rb_str_dup(str);
}
else {
return str;
}
} Если строка заморожена, возвращается дублированная изменяемая строка.
Если строка не заморожена, возвращается сама строка.
static VALUE
str_uminus(VALUE str)
{
if (OBJ_FROZEN(str)) {
return str;
}
else {
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!"
См. также #concat, который принимает несколько аргументов.
static VALUE
rb_str_cmp_m(VALUE str1, VALUE str2)
{
int result;
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
return rb_invcmp(str1, str2);
}
result = rb_str_cmp(str1, s);
return INT2FIX(result);
} Сравнение—Возвращает -1, 0, +1 или nil в зависимости от того, меньше, равно или больше string по сравнению с other_string.
Если два значения несравнимы, возвращается nil.
Если строки имеют разную длину, и они равны при сравнении до минимальной длины, то более длинная строка считается большей.
<=> — основа для методов <, <=, >, >=, и between?, включённых из модуля Comparable. Метод String#== не использует Comparable#==.
"abcdef" <=> "abcde" #=> 1 "abcdef" <=> "abcdef" #=> 0 "abcdef" <=> "abcdefg" #=> -1 "abcdef" <=> "ABCDEF" #=> 1 "abcdef" <=> 1 #=> nil
VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) {
if (!rb_respond_to(str2, idTo_str)) {
return Qfalse;
}
return rb_equal(str2, str1);
}
return str_eql(str1, str2);
} Равенство—Возвращает, является ли str == obj, аналогично Object#==.
Если obj не является экземпляром String, но отвечает на to_str, то две строки сравниваются с помощью obj.==.
В противном случае возвращается аналогично #eql?, сравнивая длину и содержимое.
VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) {
if (!rb_respond_to(str2, idTo_str)) {
return Qfalse;
}
return rb_equal(str2, str1);
}
return str_eql(str1, str2);
} Равенство—Возвращает, является ли str == obj, аналогично Object#==.
Если obj не является экземпляром String, но отвечает на to_str, то две строки сравниваются с помощью obj.==.
В противном случае возвращается аналогично #eql?, сравнивая длину и содержимое.
static VALUE
rb_str_match(VALUE x, VALUE y)
{
if (SPECIAL_CONST_P(y)) goto generic;
switch (BUILTIN_TYPE(y)) {
case T_STRING:
rb_raise(rb_eTypeError, "type mismatch: String given");
case T_REGEXP:
return rb_reg_match(y, x);
generic:
default:
return rb_funcall(y, idEqTilde, 1, x);
}
} Совпадение—Если obj является Regexp, используйте его в качестве шаблона для сопоставления со строкой str, и возвращает позицию начала совпадения, или nil если совпадения нет. В противном случае вызывается obj.=~, передавая str в качестве аргумента. По умолчанию =~ в Object возвращает nil.
Примечание: str =~ regexp не то же самое, что regexp =~
str. Строки, захваченные именованными группами захвата, присваиваются локальным переменным только во втором случае.
"cat o' 9 tails" =~ /\d/ #=> 7 "cat o' 9 tails" =~ 9 #=> nil
static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
return rb_str_subpat(str, argv[0], argv[1]);
}
else {
long beg = NUM2LONG(argv[0]);
long len = NUM2LONG(argv[1]);
return rb_str_substr(str, beg, len);
}
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0]);
} Ссылка на элемент—Если передано единственное index, возвращает подстроку из одного символа в указанном индексе. Если переданы start индекс и length, возвращает подстроку, содержащую length символов, начиная с start индекса. Если передана range, её начало и конец интерпретируются как смещения, определяющие подстроку, которая должна быть возвращена.
В этих трёх случаях, если индекс отрицательный, он отсчитывается от конца строки. Для случаев start и range начальный индекс находится непосредственно перед символом, а индекс, соответствующий размеру строки. Кроме того, пустая строка возвращается, когда начальный индекс для диапазона символов находится в конце строки.
Возвращает nil если начальный индекс выходит за пределы строки или длина отрицательна.
Если указан Regexp, возвращается соответствующая часть строки. Если за регулярным выражением следует capture, который может быть индексом или именем группы захвата, вместо этого возвращается соответствующий компонент MatchData.
Если задана match_str, возвращается эта строка, если она встречается в строке.
Возвращает nil если регулярное выражение не соответствует или строка совпадения не найдена.
a = "hello there" a[1] #=> "e" a[2, 3] #=> "llo" a[2..3] #=> "ll" a[-3, 2] #=> "er" a[7..-2] #=> "her" a[-4..-2] #=> "her" a[-2..-4] #=> "" a[11, 0] #=> "" a[11] #=> nil a[12, 0] #=> nil a[12..-1] #=> nil a[/[aeiou](.)\1/] #=> "ell" a[/[aeiou](.)\1/, 0] #=> "ell" a[/[aeiou](.)\1/, 1] #=> "l" a[/[aeiou](.)\1/, 2] #=> nil a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l" a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"] #=> "e" a["lo"] #=> "lo" a["bye"] #=> nil
static VALUE
rb_str_aset_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 3) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
}
else {
rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
}
return argv[2];
}
rb_check_arity(argc, 2, 3);
return rb_str_aset(str, argv[0], argv[1]);
} Присваивание элемента—Заменяет часть или всё содержимое строки str. Часть строки, на которую влияет присваивание, определяется так же, как и для String#[]. Если длина строки замены не равна длине заменяемого текста, строка будет соответствующим образом скорректирована. Если регулярное выражение или строка используются в качестве индекса и не соответствуют позиции в строке, генерируется IndexError. Если используется форма регулярного выражения, необязательный второй Integer позволяет указать, какую часть совпадения заменить (эффективно используя MatchData правила индексирования). Формы, которые принимают Integer, генерируют IndexError если значение вне диапазона; форма Range сгенерирует RangeError, а формы Regexp и String сгенерируют IndexError при отрицательном совпадении.
static VALUE
rb_str_is_ascii_only_p(VALUE str)
{
int cr = rb_enc_str_coderange(str);
return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse;
} Возвращает true для строки, содержащей только символы ASCII.
"abc".force_encoding("UTF-8").ascii_only? #=> true
"abc\u{6666}".force_encoding("UTF-8").ascii_only? #=> false
static VALUE
rb_str_b(VALUE str)
{
VALUE str2 = str_alloc(rb_cString);
str_replace_shared_without_enc(str2, str);
OBJ_INFECT_RAW(str2, str);
ENC_CODERANGE_CLEAR(str2);
return str2;
} Возвращает скопированную строку, кодировка которой ASCII-8BIT.
# File lib/scanf.rb, line 752
def block_scanf(fstr) #:yield: current_match
fs = Scanf::FormatString.new(fstr)
str = self.dup
final = []
begin
current = str.scanf(fs)
final.push(yield(current)) unless current.empty?
str = fs.string_left
end until current.empty? || str.empty?
return final
end Сканирует текущую строку до тех пор, пока совпадение не будет исчерпано, передавая каждое совпадение по мере его обнаружения в строке. Блок не является обязательным, так как результаты будут просто агрегированы в итоговый массив.
"123 456".block_scanf("%d")
# => [123, 456]
Если задан блок, значение, возвращаемое из него yield, добавляется к выходному массиву.
"123 456".block_scanf("%d) do |digit,| # the ',' unpacks the Array
digit + 100
end
# => [223, 556] См. Scanf для получения подробной информации о создании форматной строки.
Вам потребуется require 'scanf', чтобы использовать #block_scanf
static VALUE
rb_str_bytes(VALUE str)
{
VALUE ary = WANTARRAY("bytes", RSTRING_LEN(str));
return rb_str_enumerate_bytes(str, ary);
} Возвращает массив байтов в str. Это сокращение для str.each_byte.to_a.
Если задан блок, который является устаревшей формой, работает так же, как each_byte.
static VALUE
rb_str_bytesize(VALUE str)
{
return LONG2NUM(RSTRING_LEN(str));
} Возвращает длину str в байтах.
"\x80\u3042".bytesize #=> 4 "hello".bytesize #=> 5
static VALUE
rb_str_byteslice(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
long beg = NUM2LONG(argv[0]);
long end = NUM2LONG(argv[1]);
return str_byte_substr(str, beg, end, TRUE);
}
rb_check_arity(argc, 1, 2);
return str_byte_aref(str, argv[0]);
} Byte Reference—Если передан один Integer, возвращает подстроку из одного байта в этой позиции. Если переданы два объекта Integer, возвращает подстроку, начинающуюся с смещения, заданного первым, и длиной, заданной вторым. Если задан Range, возвращается подстрока, содержащая байты со смещениями, заданными диапазоном. Во всех трёх случаях, если смещение отрицательное, оно отсчитывается от конца str. Возвращает nil, если начальное смещение выходит за пределы строки, длина отрицательна или начало диапазона больше конца. Кодировка результирующей строки сохраняет исходную кодировку.
"hello".byteslice(1) #=> "e" "hello".byteslice(-1) #=> "o" "hello".byteslice(1, 2) #=> "el" "\x80\u3042".byteslice(1, 3) #=> "\u3042" "\x03\u3042\xff".byteslice(1..3) #=> "\u3042"
static VALUE
rb_str_capitalize(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_capitalize_bang(argc, argv, str);
return str;
} Возвращает копию str с первым символом, преобразованным в верхний регистр, а остальными — в нижний регистр.
См. #downcase для значения options и использования с различными кодировками.
"hello".capitalize #=> "Hello" "HELLO".capitalize #=> "Hello" "123ABC".capitalize #=> "123abc"
static VALUE
rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Модифицирует str, преобразуя первый символ в верхний регистр, а остальные — в нижний регистр. Возвращает nil, если изменения не были внесены.
См. #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. Это отличается от #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, возвращает новую строку длиной 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"
См. также #<<, который принимает один аргумент.
static VALUE
rb_str_count(int argc, VALUE *argv, VALUE str)
{
char table[TR_TABLE_SIZE];
rb_encoding *enc = 0;
VALUE del = 0, nodel = 0, tstr;
char *s, *send;
int i;
int ascompat;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
tstr = argv[0];
StringValue(tstr);
enc = rb_enc_check(str, tstr);
if (argc == 1) {
const char *ptstr;
if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
(ptstr = RSTRING_PTR(tstr),
ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (const unsigned char *)ptstr, (const unsigned char *)ptstr+1)) &&
!is_broken_string(str)) {
int n = 0;
int clen;
unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
send = RSTRING_END(str);
while (s < send) {
if (*(unsigned char*)s++ == c) n++;
}
return INT2NUM(n);
}
}
tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
for (i=1; i<argc; i++) {
tstr = argv[i];
StringValue(tstr);
enc = rb_enc_check(str, tstr);
tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
}
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
send = RSTRING_END(str);
ascompat = rb_enc_asciicompat(enc);
i = 0;
while (s < send) {
unsigned int c;
if (ascompat && (c = *(unsigned char*)s) < 0x80) {
if (table[c]) {
i++;
}
s++;
}
else {
int clen;
c = rb_enc_codepoint_len(s, send, &clen, enc);
if (tr_find(c, table, del, nodel)) {
i++;
}
s += clen;
}
}
return INT2NUM(i);
} Каждый параметр other_str определяет набор символов для подсчета. Пересечение этих множеств определяет символы для подсчета в str. Любой other_str, начинающийся со знака каретки ^, инвертируется. Последовательность c1-c2 означает все символы между c1 и c2. Символ обратной косой черты \ может использоваться для экранирования ^ или - и в противном случае игнорируется, если он не появляется в конце последовательности или в конце other_str.
a = "hello world" a.count "lo" #=> 5 a.count "lo", "o" #=> 2 a.count "hello", "^l" #=> 4 a.count "ej-m" #=> 4 "hello^world".count "\\^aeiou" #=> 4 "hello-world".count "a\\-eo" #=> 4 c = "hello world\\r\\n" c.count "\\" #=> 2 c.count "\\A" #=> 0 c.count "X-\\w" #=> 3
static VALUE
rb_str_crypt(VALUE str, VALUE salt)
{
#ifdef HAVE_CRYPT_R
VALUE databuf;
struct crypt_data *data;
# define CRYPT_END() ALLOCV_END(databuf)
#else
extern char *crypt(const char *, const char *);
# define CRYPT_END() (void)0
#endif
VALUE result;
const char *s, *saltp;
char *res;
#ifdef BROKEN_CRYPT
char salt_8bit_clean[3];
#endif
StringValue(salt);
mustnot_wchar(str);
mustnot_wchar(salt);
if (RSTRING_LEN(salt) < 2) {
short_salt:
rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
}
s = StringValueCStr(str);
saltp = RSTRING_PTR(salt);
if (!saltp[0] || !saltp[1]) goto short_salt;
#ifdef BROKEN_CRYPT
if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
salt_8bit_clean[0] = saltp[0] & 0x7f;
salt_8bit_clean[1] = saltp[1] & 0x7f;
salt_8bit_clean[2] = '\0';
saltp = salt_8bit_clean;
}
#endif
#ifdef HAVE_CRYPT_R
data = ALLOCV(databuf, sizeof(struct crypt_data));
# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
data->initialized = 0;
# endif
res = crypt_r(s, saltp, data);
#else
res = crypt(s, saltp);
#endif
if (!res) {
int err = errno;
CRYPT_END();
rb_syserr_fail(err, "crypt");
}
result = rb_str_new_cstr(res);
CRYPT_END();
FL_SET_RAW(result, OBJ_TAINTED_RAW(str) | OBJ_TAINTED_RAW(salt));
return result;
} Применяет односторонний криптографический хэш к str, вызывая функцию стандартной библиотеки crypt(3) с заданной строкой соли. Хотя формат и результат зависят от системы и реализации, использование соли, соответствующей регулярному выражению \A[a-zA-Z0-9./]{2}, должно быть допустимым и безопасным на любой платформе, где значимы только первые два символа.
Этот метод предназначен для использования в системно-зависимых скриптах, поэтому, если вам нужна кроссплатформенная хэш-функция, рассмотрите возможность использования Digest или OpenSSL вместо этого.
static VALUE
rb_str_delete(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_delete_bang(argc, argv, str);
return str;
} Возвращает копию str со всеми символами в пересечении его аргументов, удаленными. Использует те же правила для построения множества символов, что и String#count.
"hello".delete "l","lo" #=> "heo" "hello".delete "lo" #=> "he" "hello".delete "aeiou", "^e" #=> "hell" "hello".delete "ej-m" #=> "ho"
static VALUE
rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
{
char squeez[TR_TABLE_SIZE];
rb_encoding *enc = 0;
char *s, *send, *t;
VALUE del = 0, nodel = 0;
int modify = 0;
int i, ascompat, cr;
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i=0; i<argc; i++) {
VALUE s = argv[i];
StringValue(s);
enc = rb_enc_check(str, s);
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
str_modify_keep_cr(str);
ascompat = rb_enc_asciicompat(enc);
s = t = RSTRING_PTR(str);
send = RSTRING_END(str);
cr = ascompat ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
while (s < send) {
unsigned int c;
int clen;
if (ascompat && (c = *(unsigned char*)s) < 0x80) {
if (squeez[c]) {
modify = 1;
}
else {
if (t != s) *t = c;
t++;
}
s++;
}
else {
c = rb_enc_codepoint_len(s, send, &clen, enc);
if (tr_find(c, squeez, del, nodel)) {
modify = 1;
}
else {
if (t != s) rb_enc_mbcput(c, t, enc);
t += clen;
if (cr == ENC_CODERANGE_7BIT) cr = ENC_CODERANGE_VALID;
}
s += clen;
}
}
TERM_FILL(t, TERM_LEN(str));
STR_SET_LEN(str, t - RSTRING_PTR(str));
ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
} Выполняет операцию delete на месте, возвращая str или nil, если str не был изменен.
static VALUE
rb_str_delete_prefix(VALUE str, VALUE prefix)
{
long prefixlen;
prefixlen = deleted_prefix_length(str, prefix);
if (prefixlen <= 0) return rb_str_dup(str);
return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
} Возвращает копию str с удаленным ведущим prefix.
"hello".delete_prefix("hel") #=> "lo"
"hello".delete_prefix("llo") #=> "hello"
static VALUE
rb_str_delete_prefix_bang(VALUE str, VALUE prefix)
{
long prefixlen;
str_modify_keep_cr(str);
prefixlen = deleted_prefix_length(str, prefix);
if (prefixlen <= 0) return Qnil;
return rb_str_drop_bytes(str, prefixlen);
} Удаляет ведущий prefix из str, возвращая nil, если изменений не было.
"hello".delete_prefix!("hel") #=> "lo"
"hello".delete_prefix!("llo") #=> nil
static VALUE
rb_str_delete_suffix(VALUE str, VALUE suffix)
{
long suffixlen;
suffixlen = deleted_suffix_length(str, suffix);
if (suffixlen <= 0) return rb_str_dup(str);
return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
} Возвращает копию str с удаленным конечным suffix.
"hello".delete_suffix("llo") #=> "he"
"hello".delete_suffix("hel") #=> "hello"
static VALUE
rb_str_delete_suffix_bang(VALUE str, VALUE suffix)
{
long olen, suffixlen, len;
str_modifiable(str);
suffixlen = deleted_suffix_length(str, suffix);
if (suffixlen <= 0) return Qnil;
olen = RSTRING_LEN(str);
str_modify_keep_cr(str);
len = olen - suffixlen;
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
ENC_CODERANGE_CLEAR(str);
}
return str;
} Удаляет конечный suffix из str, возвращая nil, если изменений не было.
"hello".delete_suffix!("llo") #=> "he"
"hello".delete_suffix!("hel") #=> nil
static VALUE
rb_str_downcase(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_downcase_bang(argc, argv, str);
return str;
} Возвращает копию str со всеми заглавными буквами, замененными на их строчные аналоги. Какие именно буквы заменяются и на какие другие буквы, зависит от наличия или отсутствия параметров и от encoding строки.
Значение options следующее:
- Без параметра
-
Полное соответствие регистров Unicode, подходящее для большинства языков (см. параметры :turkic и :lithuanian ниже для исключений). Соответствие регистров в зависимости от контекста, как описано в таблице 3-14 стандарта Unicode, в настоящее время не поддерживается.
- :ascii
-
Затрагивается только область ASCII, то есть символы «A» до «Z» и «a» до «z». Этот параметр не может сочетаться ни с каким другим параметром.
- :turkic
-
Полное соответствие регистров Unicode, адаптированное для тюркских языков (турецкий, азербайджанский и т. д.). Это означает, что заглавная I сопоставляется со строчной без точки i и так далее.
- :lithuanian
-
В настоящее время это просто полное соответствие регистров Unicode. В будущем — полное соответствие регистров Unicode, адаптированное для литовского языка (сохранение точки в строчной i, даже если сверху есть акцент).
- :fold
-
Доступно только для
downcaseиdowncase!. Свертка регистра Unicode, которая имеет более широкий охват, чем соответствие регистра Unicode. В настоящее время этот параметр не может сочетаться ни с каким другим параметром (т. е. в настоящее время нет варианта для тюркских языков).
Обратите внимание, что несколько предположений, которые действительны для преобразований регистра только в ASCII, неверны для более общих преобразований регистра. Например, длина результата может не совпадать с длиной входных данных (ни в символах, ни в байтах), некоторые предположения о взаимном преобразовании (например, str.downcase == str.upcase.downcase) могут не применяться, и нормализация Unicode (т. е. #unicode_normalize) не обязательно сохраняется операциями сопоставления регистра.
Сопоставление/свертка регистра, не относящаяся к ASCII, в настоящее время поддерживается для строк/символов UTF-8, UTF-16BE/LE, UTF-32BE/LE и ISO-8859-1~16. Эта поддержка будет расширена на другие кодировки.
"hEllO".downcase #=> "hello"
static VALUE
rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (((flags&ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() || rb_enc_mbmaxlen(enc)==1))
|| (!(flags&ONIGENC_CASE_FOLD_TURKISH_AZERI) && ENC_CODERANGE(str)==ENC_CODERANGE_7BIT)) {
char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
while (s < send) {
unsigned int c = *(unsigned char*)s;
if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
*s = 'a' + (c - 'A');
flags |= ONIGENC_CASE_MODIFIED;
}
s++;
}
}
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Переводит содержимое str в нижний регистр, возвращая nil, если изменений не было.
См. #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[] = ".force_encoding(\"%s\")";
len = 2; /* "" */
if (!rb_enc_asciicompat(enc)) {
len += strlen(nonascii_suffix) - rb_strlen_lit("%s");
len += strlen(enc->name);
}
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
while (p < pend) {
int clen;
unsigned char c = *p++;
switch (c) {
case '"': case '\\':
case '\n': case '\r':
case '\t': case '\f':
case '\013': case '\010': case '\007': case '\033':
clen = 2;
break;
case '#':
clen = IS_EVSTR(p, pend) ? 2 : 1;
break;
default:
if (ISPRINT(c)) {
clen = 1;
}
else {
if (u8 && c > 0x7F) { /* \u notation */
int n = rb_enc_precise_mbclen(p-1, pend, enc);
if (MBCLEN_CHARFOUND_P(n)) {
unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
if (cc <= 0xFFFF)
clen = 6; /* \uXXXX */
else if (cc <= 0xFFFFF)
clen = 9; /* \u{XXXXX} */
else
clen = 10; /* \u{XXXXXX} */
p += MBCLEN_CHARFOUND_LEN(n)-1;
break;
}
}
clen = 4; /* \xNN */
}
break;
}
if (clen > LONG_MAX - len) {
rb_raise(rb_eRuntimeError, "string size too big");
}
len += clen;
}
result = rb_str_new_with_class(str, 0, len);
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
q = RSTRING_PTR(result); qend = q + len + 1;
*q++ = '"';
while (p < pend) {
unsigned char c = *p++;
if (c == '"' || c == '\\') {
*q++ = '\\';
*q++ = c;
}
else if (c == '#') {
if (IS_EVSTR(p, pend)) *q++ = '\\';
*q++ = '#';
}
else if (c == '\n') {
*q++ = '\\';
*q++ = 'n';
}
else if (c == '\r') {
*q++ = '\\';
*q++ = 'r';
}
else if (c == '\t') {
*q++ = '\\';
*q++ = 't';
}
else if (c == '\f') {
*q++ = '\\';
*q++ = 'f';
}
else if (c == '\013') {
*q++ = '\\';
*q++ = 'v';
}
else if (c == '\010') {
*q++ = '\\';
*q++ = 'b';
}
else if (c == '\007') {
*q++ = '\\';
*q++ = 'a';
}
else if (c == '\033') {
*q++ = '\\';
*q++ = 'e';
}
else if (ISPRINT(c)) {
*q++ = c;
}
else {
*q++ = '\\';
if (u8) {
int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
if (MBCLEN_CHARFOUND_P(n)) {
int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
p += n;
if (cc <= 0xFFFF)
snprintf(q, qend-q, "u%04X", cc); /* \uXXXX */
else
snprintf(q, qend-q, "u{%X}", cc); /* \u{XXXXX} or \u{XXXXXX} */
q += strlen(q);
continue;
}
}
snprintf(q, qend-q, "x%02X", c);
q += 3;
}
}
*q++ = '"';
*q = '\0';
if (!rb_enc_asciicompat(enc)) {
snprintf(q, qend-q, nonascii_suffix, enc->name);
encidx = rb_ascii8bit_encindex();
}
OBJ_INFECT_RAW(result, str);
/* result from dump is ASCII */
rb_enc_associate_index(result, encidx);
ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT);
return result;
} Создает версию str со всеми непечатаемыми символами, замененными на \nnn обозначение, и всеми специальными символами, экранированными.
"hello \n ''".dump #=> "\"hello \\n ''\""
static VALUE
rb_str_each_byte(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_byte_size);
return rb_str_enumerate_bytes(str, 0);
} Передает каждый байт в str в заданный блок или возвращает перечислитель, если блок не задан.
"hello".each_byte {|c| print c, ' ' }
выдает:
104 101 108 108 111
static VALUE
rb_str_each_char(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_char_size);
return rb_str_enumerate_chars(str, 0);
} Передает каждый символ в str в заданный блок или возвращает перечислитель, если блок не задан.
"hello".each_char {|c| print c, ' ' }
выдает:
h e l l o
static VALUE
rb_str_each_codepoint(VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_char_size);
return rb_str_enumerate_codepoints(str, 0);
} Передает Integer порядковый номер каждого символа в str, также известный как кодовая точка применительно к строкам 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 в заданный блок или возвращает перечислитель, если блок не задан. В отличие от #each_char, этот перечислитель работает с кластерами графем, определёнными в Приложении #29 к Стандарту Юникода unicode.org/reports/tr29/
"a\u0300".each_char.to_a.size #=> 2 "a\u0300".each_grapheme_cluster.to_a.size #=> 1
static VALUE
rb_str_each_line(int argc, VALUE *argv, VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, argc, argv, 0);
return rb_str_enumerate_lines(argc, argv, str, 0);
} Разбивает str с помощью заданного параметра в качестве разделителя записей ($/ по умолчанию), передавая каждую подстроку в блок. Если разделитель записей имеет нулевую длину, строка разбивается на абзацы, ограниченные несколькими последовательными символами новой строки.
См. IO.readlines для получения подробной информации о getline_args.
Если блок не задан, вместо него возвращается перечислитель.
print "Example one\n"
"hello\nworld".each_line {|s| p s}
print "Example two\n"
"hello\nworld".each_line('l') {|s| p s}
print "Example three\n"
"hello\n\n\nworld".each_line('') {|s| p s}
результат:
Example one "hello\n" "world" Example two "hel" "l" "o\nworl" "d" Example three "hello\n\n" "world"
static VALUE
rb_str_empty(VALUE str)
{
if (RSTRING_LEN(str) == 0)
return Qtrue;
return Qfalse;
} Возвращает true если у str длина равна нулю.
"hello".empty? #=> false " ".empty? #=> false "".empty? #=> true
static VALUE
str_encode(int argc, VALUE *argv, VALUE str)
{
VALUE newstr = str;
int encidx = str_transcode(argc, argv, &newstr);
return encoded_dup(newstr, str, encidx);
} Первый вариант возвращает копию str в кодировке encoding. Второй вариант возвращает копию str в кодировке от src_encoding до dst_encoding. Последний вариант возвращает копию str в кодировке Encoding.default_internal.
По умолчанию, первый и второй варианты выбрасывают Encoding::UndefinedConversionError для символов, неопределённых в целевой кодировке, и Encoding::InvalidByteSequenceError для недопустимых последовательностей байтов в исходной кодировке. Последний вариант по умолчанию не выбрасывает исключений, а использует строки замены.
Хэш options Hash даёт подробности для преобразования и может содержать следующие ключи:
- :invalid
-
Если значение
:replace, encode заменяет некорректные последовательности байтов вstrсимволом замены. По умолчанию генерируется исключение Encoding::InvalidByteSequenceError - :undef
-
Если значение
:replace, encode заменяет символы, не определённые в целевой кодировке, символом замены. По умолчанию генерируется исключение Encoding::UndefinedConversionError. - :replace
-
Устанавливает строку замены на заданное значение. Строка замены по умолчанию — “uFFFD” для кодировок Юникода и “?” в противном случае.
- :fallback
-
Устанавливает строку замены заданным объектом для неопределённых символов. Объект должен быть Hash, Proc, Method или объектом, имеющим метод []. Его ключом является неопределённый символ, закодированный в исходной кодировке текущего преобразователя. Его значением может быть любая кодировка, пока она может быть преобразована в целевую кодировку преобразователя.
- :xml
-
Значение должно быть
:textили:attr. Если значение:text, encode заменяет неопределённые символы их числовыми ссылками (в верхнем регистре в шестнадцатеричном формате). '&', '<', и '>' преобразуются соответственно в “&”, “<”, и “>”. Если значение:attr, encode также приводит результат замены в кавычки (используя '“') и заменяет '”' на “"”. - :cr_newline
-
Заменяет LF (“n”) на CR (“r”), если значение истинно.
- :crlf_newline
-
Заменяет LF (“n”) на CRLF (“rn”), если значение истинно.
- :universal_newline
-
Заменяет CRLF (“rn”) и CR (“r”) на LF (“n”), если значение истинно.
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 содержат детали преобразования. См. #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
VALUE
rb_str_eql(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
return str_eql(str1, str2);
} Две строки равны, если они имеют одинаковую длину и содержимое.
static VALUE
rb_str_force_encoding(VALUE str, VALUE enc)
{
str_modifiable(str);
rb_enc_associate(str, rb_to_encoding(enc));
ENC_CODERANGE_CLEAR(str);
return str;
} Изменяет кодировку на encoding и возвращает self.
VALUE
rb_str_freeze(VALUE str)
{
if (OBJ_FROZEN(str)) return str;
rb_str_resize(str, RSTRING_LEN(str));
return rb_obj_freeze(str);
} static VALUE
rb_str_getbyte(VALUE str, VALUE index)
{
long pos = NUM2LONG(index);
if (pos < 0)
pos += RSTRING_LEN(str);
if (pos < 0 || RSTRING_LEN(str) <= pos)
return Qnil;
return INT2FIX((unsigned char)RSTRING_PTR(str)[pos]);
} Возвращает байт с индексом index как целое число.
static VALUE
rb_str_grapheme_clusters(VALUE str)
{
VALUE ary = WANTARRAY("grapheme_clusters", rb_str_strlen(str));
return rb_str_enumerate_grapheme_clusters(str, ary);
} Возвращает массив кластеров графем в str. Это сокращение для str.each_grapheme_cluster.to_a.
Если задан блок (устаревшая форма), работает так же, как each_grapheme_cluster.
static VALUE
rb_str_gsub(int argc, VALUE *argv, VALUE str)
{
return str_gsub(argc, argv, str, 0);
} Возвращает копию str с всеми вхождениями pattern, заменёнными на второе значение. pattern обычно представляет собой Regexp; если он задан как String, все метасимволы регулярных выражений в нём будут интерпретированы буквально, например, '\\d' будет соответствовать обратной косой черте, за которой следует «d», вместо цифры.
Если replacement является String, он будет заменён на сопоставленный текст. Он может содержать обратные ссылки на группы захвата шаблона в виде \\d, где d — номер группы, или \\k<n>, где n — имя группы. Если это строка в двойных кавычках, обе обратные ссылки должны предваряться дополнительной обратной косой чертой. Однако внутри replacement специальные переменные соответствия, такие как $&, не будут относиться к текущему соответствию.
Если второе значение является Hash, а сопоставленный текст является одним из его ключей, соответствующее значение является строкой замены.
В блочной форме текущая строка соответствия передаётся в качестве параметра, и такие переменные, как $1, $2, $`, $&, и $', будут установлены должным образом. Возвращаемое блоком значение будет заменено на соответствие на каждом вызове.
Результат наследует любые метки, присутствующие в исходной строке или любой предоставленной строке замены.
Когда не задан ни блок, ни второе значение, возвращается Enumerator.
"hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"
static VALUE
rb_str_gsub_bang(int argc, VALUE *argv, VALUE str)
{
str_modify_keep_cr(str);
return str_gsub(argc, argv, str, 1);
} Выполняет замены String#gsub на месте, возвращая str или nil если замен не было. Если не задан ни блок, ни replacement, вместо этого возвращается перечислитель.
static VALUE
rb_str_hash_m(VALUE str)
{
st_index_t hval = rb_str_hash(str);
return ST2FIX(hval);
} Возвращает хэш, основанный на длине, содержании и кодировке строки.
См. также Object#hash.
static VALUE
rb_str_hex(VALUE str)
{
return rb_str_to_inum(str, 16, FALSE);
} Обрабатывает ведущие символы из str как строку шестнадцатеричных цифр (с необязательным знаком и необязательным 0x) и возвращает соответствующее число. В случае ошибки возвращается ноль.
"0x0a".hex #=> 10 "-1234".hex #=> -4660 "0".hex #=> 0 "wombat".hex #=> 0
static VALUE
rb_str_include(VALUE str, VALUE arg)
{
long i;
StringValue(arg);
i = rb_str_index(str, arg, 0);
if (i == -1) return Qfalse;
return Qtrue;
} Возвращает true если str содержит заданную строку или символ.
"hello".include? "lo" #=> true "hello".include? "ol" #=> false "hello".include? ?h #=> true
static VALUE
rb_str_index_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE initpos;
long pos;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
pos = NUM2LONG(initpos);
}
else {
pos = 0;
}
if (pos < 0) {
pos += str_strlen(str, NULL);
if (pos < 0) {
if (RB_TYPE_P(sub, T_REGEXP)) {
rb_backref_set(Qnil);
}
return Qnil;
}
}
if (SPECIAL_CONST_P(sub)) goto generic;
switch (BUILTIN_TYPE(sub)) {
case T_REGEXP:
if (pos > str_strlen(str, NULL))
return Qnil;
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
rb_enc_check(str, sub), single_byte_optimizable(str));
pos = rb_reg_search(sub, str, pos, 0);
pos = rb_str_sublen(str, pos);
break;
generic:
default: {
VALUE tmp;
tmp = rb_check_string_type(sub);
if (NIL_P(tmp)) {
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_obj_classname(sub));
}
sub = tmp;
}
/* fall through */
case T_STRING:
pos = rb_str_index(str, sub, pos);
pos = rb_str_sublen(str, pos);
break;
}
if (pos == -1) return Qnil;
return LONG2NUM(pos);
} Возвращает индекс первого вхождения заданного substring или шаблона (regexp) в str. Возвращает nil если не найдено. Если присутствует второй параметр, он определяет позицию в строке, с которой начать поиск.
"hello".index('e') #=> 1
"hello".index('lo') #=> 3
"hello".index('a') #=> nil
"hello".index(?e) #=> 1
"hello".index(/[aeiou]/, -3) #=> 4
VALUE
rb_str_replace(VALUE str, VALUE str2)
{
str_modifiable(str);
if (str == str2) return str;
StringValue(str2);
str_discard(str);
return str_replace(str, str2);
} Заменяет содержимое и отмеченность str соответствующими значениями в other_str.
s = "hello" #=> "hello" s.replace "world" #=> "world"
static VALUE
rb_str_insert(VALUE str, VALUE idx, VALUE str2)
{
long pos = NUM2LONG(idx);
if (pos == -1) {
return rb_str_append(str, str2);
}
else if (pos < 0) {
pos++;
}
rb_str_splice(str, pos, 0, str2);
return str;
} Вставляет other_str перед символом по заданному index, изменяя str. Отрицательные индексы отсчитываются с конца строки и вставляют after заданного символа. Цель состоит в том, чтобы вставить aString так, чтобы он начинался по данному index.
"abcd".insert(0, 'X') #=> "Xabcd" "abcd".insert(3, 'X') #=> "abcXd" "abcd".insert(4, 'X') #=> "abcdX" "abcd".insert(-3, 'X') #=> "abXcd" "abcd".insert(-1, 'X') #=> "abcdX"
VALUE
rb_str_inspect(VALUE str)
{
int encidx = ENCODING_GET(str);
rb_encoding *enc = rb_enc_from_index(encidx), *actenc;
const char *p, *pend, *prev;
char buf[CHAR_ESC_LEN + 1];
VALUE result = rb_str_buf_new(0);
rb_encoding *resenc = rb_default_internal_encoding();
int unicode_p = rb_enc_unicode_p(enc);
int asciicompat = rb_enc_asciicompat(enc);
if (resenc == NULL) resenc = rb_default_external_encoding();
if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
rb_enc_associate(result, resenc);
str_buf_cat2(result, "\"");
p = RSTRING_PTR(str); pend = RSTRING_END(str);
prev = p;
actenc = get_actual_encoding(encidx, str);
if (actenc != enc) {
enc = actenc;
if (unicode_p) unicode_p = rb_enc_unicode_p(enc);
}
while (p < pend) {
unsigned int c, cc;
int n;
n = rb_enc_precise_mbclen(p, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
if (p > prev) str_buf_cat(result, prev, p - prev);
n = rb_enc_mbminlen(enc);
if (pend < p + n)
n = (int)(pend - p);
while (n--) {
snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377);
str_buf_cat(result, buf, strlen(buf));
prev = ++p;
}
continue;
}
n = MBCLEN_CHARFOUND_LEN(n);
c = rb_enc_mbc_to_codepoint(p, pend, enc);
p += n;
if ((asciicompat || unicode_p) &&
(c == '"'|| c == '\\' ||
(c == '#' &&
p < pend &&
MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
(cc = rb_enc_codepoint(p,pend,enc),
(cc == '$' || cc == '@' || cc == '{'))))) {
if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
str_buf_cat2(result, "\\");
if (asciicompat || enc == resenc) {
prev = p - n;
continue;
}
}
switch (c) {
case '\n': cc = 'n'; break;
case '\r': cc = 'r'; break;
case '\t': cc = 't'; break;
case '\f': cc = 'f'; break;
case '\013': cc = 'v'; break;
case '\010': cc = 'b'; break;
case '\007': cc = 'a'; break;
case 033: cc = 'e'; break;
default: cc = 0; break;
}
if (cc) {
if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
buf[0] = '\\';
buf[1] = (char)cc;
str_buf_cat(result, buf, 2);
prev = p;
continue;
}
if ((enc == resenc && rb_enc_isprint(c, enc)) ||
(asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
continue;
}
else {
if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
rb_str_buf_cat_escaped_char(result, c, unicode_p);
prev = p;
continue;
}
}
if (p > prev) str_buf_cat(result, prev, p - prev);
str_buf_cat2(result, "\"");
OBJ_INFECT_RAW(result, str);
return result;
} Возвращает удобочитаемый вид str, заключённый в кавычки, со специальными символами, экранированными.
str = "hello" str[3] = "\b" str.inspect #=> "\"hel\\bo\""
VALUE
rb_str_intern(VALUE str)
{
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
int type;
#else
ID id;
#endif
VALUE sym = lookup_str_sym(str);
if (sym) {
return sym;
}
#if USE_SYMBOL_GC
enc = rb_enc_get(str);
ascii = rb_usascii_encoding();
if (enc != ascii && sym_check_asciionly(str)) {
str = rb_str_dup(str);
rb_enc_associate(str, ascii);
OBJ_FREEZE(str);
enc = ascii;
}
else {
str = rb_str_new_frozen(str);
}
str = rb_fstring(str);
type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
if (type < 0) type = ID_JUNK;
return dsymbol_alloc(rb_cSymbol, str, enc, type);
#else
id = intern_str(str, 0);
return ID2SYM(id);
#endif
} Возвращает Symbol, соответствующую str, создавая символ, если он ранее не существовал. См. Symbol#id2name.
"Koala".intern #=> :Koala s = 'cat'.to_sym #=> :cat s == :cat #=> true s = '@cat'.to_sym #=> :@cat s == :@cat #=> true
Это также можно использовать для создания символов, которые нельзя представить с помощью :xxx.
'cat and dog'.to_sym #=> :"cat and dog"
VALUE
rb_str_length(VALUE str)
{
return LONG2NUM(str_strlen(str, NULL));
} Возвращает длину str в символах.
static VALUE
rb_str_lines(int argc, VALUE *argv, VALUE str)
{
VALUE ary = WANTARRAY("lines", 0);
return rb_str_enumerate_lines(argc, argv, str, ary);
} Возвращает массив строк в str, разделенных с помощью заданного разделителя записей ($/ по умолчанию). Это сокращённая запись для str.each_line(separator).to_a.
Если задан блок, что является устаревшей формой, работает так же, как и each_line.
static VALUE
rb_str_ljust(int argc, VALUE *argv, VALUE str)
{
return rb_str_justify(argc, argv, str, 'l');
} Если integer больше длины str, возвращает новую String длиной integer с str, выровненной влево и дополненной padstr; в противном случае возвращает str.
"hello".ljust(4) #=> "hello" "hello".ljust(20) #=> "hello " "hello".ljust(20, '1234') #=> "hello123412341234123"
static VALUE
rb_str_lstrip(VALUE str)
{
char *start;
long len, loffset;
RSTRING_GETMEM(str, start, len);
loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
if (loffset <= 0) return rb_str_dup(str);
return rb_str_subseq(str, loffset, len - loffset);
} Возвращает копию str с удаленными начальными пробелами. См. также String#rstrip и String#strip.
Обратитесь к 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;
} Удаляет начальные пробелы из str, возвращая nil если изменений не было. См. также String#rstrip! и String#strip!.
Обратитесь к strip для определения пробелов.
" hello ".lstrip! #=> "hello " "hello ".lstrip! #=> nil "hello".lstrip! #=> nil
static VALUE
rb_str_match_m(int argc, VALUE *argv, VALUE str)
{
VALUE re, result;
if (argc < 1)
rb_check_arity(argc, 1, 2);
re = argv[0];
argv[0] = str;
result = rb_funcallv(get_pat(re), rb_intern("match"), argc, argv);
if (!NIL_P(result) && rb_block_given_p()) {
return rb_yield(result);
}
return result;
} Преобразует pattern в Regexp (если это не так), затем вызывает его метод match для str. Если второй параметр присутствует, он определяет позицию в строке, с которой начать поиск.
'hello'.match('(.)\1') #=> #<MatchData "ll" 1:"l">
'hello'.match('(.)\1')[0] #=> "ll"
'hello'.match(/(.)\1/)[0] #=> "ll"
'hello'.match(/(.)\1/, 3) #=> nil
'hello'.match('xx') #=> nil
Если блок задан, вызовите блок с MatchData, если соответствие найдено, чтобы вы могли написать
str.match(pat) {|m| ...} вместо
if m = str.match(pat) ... end
В этом случае возвращаемое значение — результат выполнения блока.
static VALUE
rb_str_match_m_p(int argc, VALUE *argv, VALUE str)
{
VALUE re;
rb_check_arity(argc, 1, 2);
re = get_pat(argv[0]);
return rb_reg_match_p(re, str, argc > 1 ? NUM2LONG(argv[1]) : 0);
} Преобразует pattern в Regexp (если это ещё не так), затем возвращает true или false указывает, соответствует ли regexp str или нет, не обновляя $~ и другие связанные переменные. Если присутствует второй параметр, он указывает позицию в строке, с которой следует начинать поиск.
"Ruby".match?(/R.../) #=> true "Ruby".match?(/R.../, 1) #=> false "Ruby".match?(/P.../) #=> false $& #=> nil
VALUE
rb_str_succ(VALUE orig)
{
VALUE str;
str = rb_str_new_with_class(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
rb_enc_cr_str_copy_for_substr(str, orig);
OBJ_INFECT(str, orig);
return str_succ(str);
} Возвращает следующий за str элемент. Следующий элемент вычисляется путем инкрементирования символов, начиная с самого правого буквенно-цифрового символа (или самого правого символа, если буквенно-цифровых символов нет) в строке. Инкрементирование цифры всегда приводит к другой цифре, а инкрементирование буквы приводит к другой букве того же регистра. Инкрементирование неалфавитно-цифровых символов использует порядок сортировки базового набора символов.
Если инкремент генерирует «перенос», то инкрементируется символ слева от него. Этот процесс повторяется до тех пор, пока не будет переноса, при необходимости добавляя дополнительный символ.
"abcd".succ #=> "abce" "THX1138".succ #=> "THX1139" "<<koala>>".succ #=> "<<koalb>>" "1999zzz".succ #=> "2000aaa" "ZZZ9999".succ #=> "AAAA0000" "***".succ #=> "**+"
static VALUE
rb_str_succ_bang(VALUE str)
{
rb_str_modify(str);
str_succ(str);
return str;
} Эквивалентно String#succ, но изменяет получатель на месте.
static VALUE
rb_str_oct(VALUE str)
{
return rb_str_to_inum(str, -8, FALSE);
} Рассматривает начальные символы str как строку восьмеричных цифр (с необязательным знаком) и возвращает соответствующее число. Возвращает 0, если преобразование не удается.
"123".oct #=> 83 "-377".oct #=> -255 "bad".oct #=> 0 "0377bad".oct #=> 255
Если str начинается с 0, учитываются индикаторы основания. См. Kernel#Integer.
VALUE
rb_str_ord(VALUE s)
{
unsigned int c;
c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s));
return UINT2NUM(c);
} Возвращает Integer порядковый номер односимвольной строки.
"a".ord #=> 97
static VALUE
rb_str_partition(VALUE str, VALUE sep)
{
long pos;
sep = get_pat_quoted(sep, 0);
if (RB_TYPE_P(sep, T_REGEXP)) {
pos = rb_reg_search(sep, str, 0, 0);
if (pos < 0) {
failed:
return rb_ary_new3(3, rb_str_dup(str), str_new_empty(str), str_new_empty(str));
}
sep = rb_str_subpat(str, sep, INT2FIX(0));
if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed;
}
else {
pos = rb_str_index(str, sep, 0);
if (pos < 0) goto failed;
}
return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
sep,
rb_str_subseq(str, pos+RSTRING_LEN(sep),
RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
} Ищет sep или шаблон (regexp) в строке и возвращает часть перед ним, совпадение и часть после него. Если он не найден, возвращает две пустые строки и str.
"hello".partition("l") #=> ["he", "l", "lo"]
"hello".partition("x") #=> ["hello", "", ""]
"hello".partition(/.l/) #=> ["h", "el", "lo"]
static VALUE
rb_str_prepend_multi(int argc, VALUE *argv, VALUE str)
{
str_modifiable(str);
if (argc == 1) {
rb_str_update(str, 0L, 0L, argv[0]);
}
else if (argc > 1) {
int i;
VALUE arg_str = rb_str_tmp_new(0);
rb_enc_copy(arg_str, str);
for (i = 0; i < argc; i++) {
rb_str_append(arg_str, argv[i]);
}
rb_str_update(str, 0L, 0L, arg_str);
}
return str;
} Добавить в начало—Добавить заданные строки в начало str.
a = "!"
a.prepend("hello ", "world") #=> "hello world!"
a #=> "hello world!"
См. также #concat.
VALUE
rb_str_replace(VALUE str, VALUE str2)
{
str_modifiable(str);
if (str == str2) return str;
StringValue(str2);
str_discard(str);
return str_replace(str, str2);
} Заменяет содержимое и зараженность str соответствующими значениями в other_str.
s = "hello" #=> "hello" s.replace "world" #=> "world"
static VALUE
rb_str_reverse(VALUE str)
{
rb_encoding *enc;
VALUE rev;
char *s, *e, *p;
int cr;
if (RSTRING_LEN(str) <= 1) return rb_str_dup(str);
enc = STR_ENC_GET(str);
rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
s = RSTRING_PTR(str); e = RSTRING_END(str);
p = RSTRING_END(rev);
cr = ENC_CODERANGE(str);
if (RSTRING_LEN(str) > 1) {
if (single_byte_optimizable(str)) {
while (s < e) {
*--p = *s++;
}
}
else if (cr == ENC_CODERANGE_VALID) {
while (s < e) {
int clen = rb_enc_fast_mbclen(s, e, enc);
p -= clen;
memcpy(p, s, clen);
s += clen;
}
}
else {
cr = rb_enc_asciicompat(enc) ?
ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
while (s < e) {
int clen = rb_enc_mbclen(s, e, enc);
if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN;
p -= clen;
memcpy(p, s, clen);
s += clen;
}
}
}
STR_SET_LEN(rev, RSTRING_LEN(str));
OBJ_INFECT_RAW(rev, str);
str_enc_copy(rev, str);
ENC_CODERANGE_SET(rev, cr);
return rev;
} Возвращает новую строку с символами из str в обратном порядке.
"stressed".reverse #=> "desserts"
static VALUE
rb_str_reverse_bang(VALUE str)
{
if (RSTRING_LEN(str) > 1) {
if (single_byte_optimizable(str)) {
char *s, *e, c;
str_modify_keep_cr(str);
s = RSTRING_PTR(str);
e = RSTRING_END(str) - 1;
while (s < e) {
c = *s;
*s++ = *e;
*e-- = c;
}
}
else {
str_shared_replace(str, rb_str_reverse(str));
}
}
else {
str_modify_keep_cr(str);
}
return str;
} Разворачивает str на месте.
static VALUE
rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE vpos;
rb_encoding *enc = STR_ENC_GET(str);
long pos, len = str_strlen(str, enc); /* str's enc */
if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
pos = NUM2LONG(vpos);
if (pos < 0) {
pos += len;
if (pos < 0) {
if (RB_TYPE_P(sub, T_REGEXP)) {
rb_backref_set(Qnil);
}
return Qnil;
}
}
if (pos > len) pos = len;
}
else {
pos = len;
}
if (SPECIAL_CONST_P(sub)) goto generic;
switch (BUILTIN_TYPE(sub)) {
case T_REGEXP:
/* enc = rb_get_check(str, sub); */
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
enc, single_byte_optimizable(str));
pos = rb_reg_search(sub, str, pos, 1);
pos = rb_str_sublen(str, pos);
if (pos >= 0) return LONG2NUM(pos);
break;
generic:
default: {
VALUE tmp;
tmp = rb_check_string_type(sub);
if (NIL_P(tmp)) {
rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_obj_classname(sub));
}
sub = tmp;
}
/* fall through */
case T_STRING:
pos = rb_str_rindex(str, sub, pos);
if (pos >= 0) return LONG2NUM(pos);
break;
}
return Qnil;
} Возвращает индекс последнего вхождения заданной substring или шаблона (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);
} Возвращает копию str с удаленными завершающими пробелами. См. также String#lstrip и String#strip.
Обратитесь к 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;
} Удаляет завершающие пробелы из str, возвращая nil, если изменений не было. См. также String#lstrip! и String#strip!.
Обратитесь к strip за определением пробелов.
" hello ".rstrip! #=> " hello" " hello".rstrip! #=> nil "hello".rstrip! #=> nil
static VALUE
rb_str_scan(VALUE str, VALUE pat)
{
VALUE result;
long start = 0;
long last = -1, prev = 0;
char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str);
pat = get_pat_quoted(pat, 1);
mustnot_broken(str);
if (!rb_block_given_p()) {
VALUE ary = rb_ary_new();
while (!NIL_P(result = scan_once(str, pat, &start, 0))) {
last = prev;
prev = start;
rb_ary_push(ary, result);
}
if (last >= 0) rb_pat_search(pat, str, last, 1);
else rb_backref_set(Qnil);
return ary;
}
while (!NIL_P(result = scan_once(str, pat, &start, 1))) {
last = prev;
prev = start;
rb_yield(result);
str_mod_check(str, p, len);
}
if (last >= 0) rb_pat_search(pat, str, last, 1);
return str;
} Обе формы итеративно обрабатывают str, сопоставляя шаблон (который может быть Regexp или String). Для каждого совпадения генерируется результат, который либо добавляется в результирующий массив, либо передается в блок. Если шаблон не содержит групп, каждый отдельный результат состоит из совпавшей строки, $&. Если шаблон содержит группы, каждый отдельный результат сам по себе является массивом, содержащим по одной записи на каждую группу.
a = "cruel world" a.scan(/\w+/) #=> ["cruel", "world"] a.scan(/.../) #=> ["cru", "el ", "wor"] a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
И форма с блоком:
a.scan(/\w+/) {|w| print "<<#{w}>> " }
print "\n"
a.scan(/(.)(.)/) {|x,y| print y, x }
print "\n"
выдает:
<<cruel>> <<world>> rceu lowlr
# File lib/scanf.rb, line 719
def scanf(fstr,&b) #:yield: current_match
if b
block_scanf(fstr,&b)
else
fs =
if fstr.is_a? Scanf::FormatString
fstr
else
Scanf::FormatString.new(fstr)
end
fs.match(self)
end
end Сканирует текущую строку. Если задан блок, он работает точно так же, как block_scanf.
arr = "123 456".scanf("%d%d")
# => [123, 456]
require 'pp'
"this 123 read that 456 other".scanf("%s%d%s") {|m| pp m}
# ["this", 123, "read"]
# ["that", 456, "other"]
# => [["this", 123, "read"], ["that", 456, "other"]]
См. Scanf для получения подробной информации о создании строки формата.
Вам потребуется require 'scanf', чтобы использовать #scanf
static VALUE
str_scrub(int argc, VALUE *argv, VALUE str)
{
VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
VALUE new = rb_str_scrub(str, repl);
return NIL_P(new) ? rb_str_dup(str): new;
} Если строка является недопустимой последовательностью байтов, замените недопустимые байты заданным символом замены, иначе верните self. Если задан блок, замените недопустимые байты возвращаемым значением блока.
"abc\u3042\x81".scrub #=> "abc\u3042\uFFFD"
"abc\u3042\x81".scrub("*") #=> "abc\u3042*"
"abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
static VALUE
str_scrub_bang(int argc, VALUE *argv, VALUE str)
{
VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
VALUE new = rb_str_scrub(str, repl);
if (!NIL_P(new)) rb_str_replace(str, new);
return str;
} Если строка содержит недопустимую последовательность байтов, то заменяет недопустимые байты заданным символом-заменителем, иначе возвращает self. Если передан блок, то заменяет недопустимые байты возвращаемым значением блока.
"abc\u3042\x81".scrub! #=> "abc\u3042\uFFFD"
"abc\u3042\x81".scrub!("*") #=> "abc\u3042*"
"abc\u3042\xE3\x80".scrub!{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
static VALUE
rb_str_setbyte(VALUE str, VALUE index, VALUE value)
{
long pos = NUM2LONG(index);
int byte = NUM2INT(value);
long len = RSTRING_LEN(str);
char *head, *ptr, *left = 0;
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;
if (!str_independent(str))
str_make_independent(str);
enc = STR_ENC_GET(str);
head = RSTRING_PTR(str);
ptr = &head[pos];
if (!STR_EMBED_P(str)) {
cr = ENC_CODERANGE(str);
switch (cr) {
case ENC_CODERANGE_7BIT:
left = 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 214 def shellescape Shellwords.escape(self) end
Экранирует str так, чтобы его можно было безопасно использовать в командной строке оболочки Bourne.
Подробности см. в Shellwords#shellescape.
# File lib/shellwords.rb, line 203 def shellsplit Shellwords.split(self) end
Разделяет str на массив токенов так же, как это делает оболочка Bourne UNIX.
Подробности см. в Shellwords#shellsplit.
VALUE
rb_str_length(VALUE str)
{
return LONG2NUM(str_strlen(str, NULL));
} Возвращает длину строки str в символах.
static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
return rb_str_subpat(str, argv[0], argv[1]);
}
else {
long beg = NUM2LONG(argv[0]);
long len = NUM2LONG(argv[1]);
return rb_str_substr(str, beg, len);
}
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0]);
} Ссылка на элемент — Если передан единственный index, возвращает подстроку из одного символа в указанном индексе. Если передан start индекс и length, возвращает подстроку, содержащую length символов, начиная с start индекса. Если передан range, его начало и конец интерпретируются как смещения, определяющие подстроку, которая должна быть возвращена.
В этих трёх случаях, если индекс отрицательный, он отсчитывается с конца строки. Для start и range случаев начальный индекс находится как раз перед символом, а индекс, соответствующий размеру строки. Кроме того, пустая строка возвращается, когда начальный индекс диапазона символов находится в конце строки.
Возвращает nil если начальный индекс выходит за пределы строки или длина отрицательна.
Если передан Regexp, возвращается соответствующая часть строки. Если за регулярным выражением следует capture, который может быть индексом или именем группы захвата, то вместо этого возвращается соответствующий компонент MatchData.
Если передан match_str, возвращается эта строка, если она встречается в строке.
Возвращает nil если регулярное выражение не соответствует или искомая подстрока не найдена.
a = "hello there" a[1] #=> "e" a[2, 3] #=> "llo" a[2..3] #=> "ll" a[-3, 2] #=> "er" a[7..-2] #=> "her" a[-4..-2] #=> "her" a[-2..-4] #=> "" a[11, 0] #=> "" a[11] #=> nil a[12, 0] #=> nil a[12..-1] #=> nil a[/[aeiou](.)\1/] #=> "ell" a[/[aeiou](.)\1/, 0] #=> "ell" a[/[aeiou](.)\1/, 1] #=> "l" a[/[aeiou](.)\1/, 2] #=> nil a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l" a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"] #=> "e" a["lo"] #=> "lo" a["bye"] #=> nil
static VALUE
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
{
VALUE result;
VALUE buf[3];
int i;
rb_check_arity(argc, 1, 2);
for (i=0; i<argc; i++) {
buf[i] = argv[i];
}
str_modify_keep_cr(str);
result = rb_str_aref_m(argc, buf, str);
if (!NIL_P(result)) {
buf[i] = rb_str_new(0,0);
rb_str_aset_m(argc+1, buf, str);
}
return result;
} Удаляет указанную часть из str и возвращает удалённую часть.
string = "this is a string"
string.slice!(2) #=> "i"
string.slice!(3..6) #=> " is "
string.slice!(/s.*t/) #=> "sa st"
string.slice!("r") #=> "r"
string #=> "thing"
static VALUE
rb_str_split_m(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
VALUE spat;
VALUE limit;
enum {awk, string, regexp} split_type;
long beg, end, i = 0;
int lim = 0;
VALUE result, tmp;
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 rb_ary_new2(0);
return rb_ary_new3(1, rb_str_dup(str));
}
i = 1;
}
enc = STR_ENC_GET(str);
split_type = regexp;
if (!NIL_P(spat)) {
spat = get_pat_quoted(spat, 0);
}
else if (NIL_P(spat = rb_fs)) {
split_type = awk;
}
else if (!(spat = rb_fs_check(spat))) {
rb_raise(rb_eTypeError, "value of $; must be String or Regexp");
}
if (split_type != awk) {
if (BUILTIN_TYPE(spat) == T_STRING) {
rb_encoding *enc2 = STR_ENC_GET(spat);
mustnot_broken(spat);
split_type = string;
if (RSTRING_LEN(spat) == 0) {
/* Special case - split into chars */
spat = rb_reg_regcomp(spat);
split_type = regexp;
}
else if (rb_enc_asciicompat(enc2) == 1) {
if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
split_type = awk;
}
}
else {
int l;
if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' &&
RSTRING_LEN(spat) == l) {
split_type = awk;
}
}
}
}
result = rb_ary_new();
beg = 0;
if (split_type == awk) {
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
char *bptr = ptr;
int skip = 1;
unsigned int c;
end = beg;
if (is_ascii_string(str)) {
while (ptr < eptr) {
c = (unsigned char)*ptr++;
if (skip) {
if (ascii_isspace(c)) {
beg = ptr - bptr;
}
else {
end = ptr - bptr;
skip = 0;
if (!NIL_P(limit) && lim <= i) break;
}
}
else if (ascii_isspace(c)) {
rb_ary_push(result, rb_str_subseq(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)) {
rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
skip = 1;
beg = ptr - bptr;
if (!NIL_P(limit)) ++i;
}
else {
end = ptr - bptr;
}
}
}
}
else if (split_type == string) {
char *ptr = RSTRING_PTR(str);
char *str_start = ptr;
char *substr_start = ptr;
char *eptr = RSTRING_END(str);
char *sptr = RSTRING_PTR(spat);
long slen = RSTRING_LEN(spat);
mustnot_broken(str);
enc = rb_enc_check(str, spat);
while (ptr < eptr &&
(end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
/* Check we are at the start of a char */
char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
if (t != ptr + end) {
ptr = t;
continue;
}
rb_ary_push(result, rb_str_subseq(str, substr_start - str_start,
(ptr+end) - substr_start));
ptr += end + slen;
substr_start = ptr;
if (!NIL_P(limit) && lim <= ++i) break;
}
beg = ptr - str_start;
}
else {
char *ptr = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
long start = beg;
long idx;
int last_null = 0;
struct re_registers *regs;
while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
regs = RMATCH_REGS(rb_backref_get());
if (start == end && BEG(0) == END(0)) {
if (!ptr) {
rb_ary_push(result, str_new_empty(str));
break;
}
else if (last_null == 1) {
rb_ary_push(result, rb_str_subseq(str, beg,
rb_enc_fast_mbclen(ptr+beg,
ptr+len,
enc)));
beg = start;
}
else {
if (start == len)
start++;
else
start += rb_enc_fast_mbclen(ptr+start,ptr+len,enc);
last_null = 1;
continue;
}
}
else {
rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
beg = start = END(0);
}
last_null = 0;
for (idx=1; idx < regs->num_regs; idx++) {
if (BEG(idx) == -1) continue;
if (BEG(idx) == END(idx))
tmp = str_new_empty(str);
else
tmp = rb_str_subseq(str, BEG(idx), END(idx)-BEG(idx));
rb_ary_push(result, tmp);
}
if (!NIL_P(limit) && lim <= ++i) break;
}
}
if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
if (RSTRING_LEN(str) == beg)
tmp = str_new_empty(str);
else
tmp = rb_str_subseq(str, beg, RSTRING_LEN(str)-beg);
rb_ary_push(result, tmp);
}
if (NIL_P(limit) && lim == 0) {
long len;
while ((len = RARRAY_LEN(result)) > 0 &&
(tmp = RARRAY_AREF(result, len-1), RSTRING_LEN(tmp) == 0))
rb_ary_pop(result);
}
return result;
} Делит str на подстроки на основе разделителя, возвращая массив этих подстрок.
Если pattern — это String, то его содержимое используется в качестве разделителя при разделении str. Если pattern — это пробел, то str разделяется по пробелам, при этом ведущие пробелы и серии пробелов игнорируются.
Если pattern — это Regexp, то str разделяется там, где совпадает шаблон. Всякий раз, когда шаблон соответствует нулевой длине строки, str разделяется на отдельные символы. Если pattern содержит группы, то соответствующие совпадения также будут возвращены в массиве.
Если pattern — это nil, то используется значение $;. Если $; — nil (по умолчанию), то str разделяется по пробелам так, как если бы был указан ' '.
Если параметр limit опущен, хвостовые нулевые поля подавляются. Если limit — положительное число, то возвращается не более этого числа подстрок разбиения (захваченные группы также возвращаются, но не учитываются при подсчете предела). Если limit — 1, то вся строка возвращается как единственный элемент массива. Если отрицательный, нет ограничения на количество возвращаемых полей, и хвостовые нулевые поля не подавляются.
Когда входная str пустая, возвращается пустой массив, так как строка считается не имеющей полей для разделения.
" 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;
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 = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
send = RSTRING_END(str);
save = -1;
ascompat = rb_enc_asciicompat(enc);
if (singlebyte) {
while (s < send) {
unsigned int c = *(unsigned char*)s++;
if (c != save || (argc > 0 && !squeez[c])) {
*t++ = save = c;
}
}
}
else {
while (s < send) {
unsigned int c;
int clen;
if (ascompat && (c = *(unsigned char*)s) < 0x80) {
if (c != save || (argc > 0 && !squeez[c])) {
*t++ = save = c;
}
s++;
}
else {
c = rb_enc_codepoint_len(s, 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(t, TERM_LEN(str));
if (t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
STR_SET_LEN(str, 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];
switch (TYPE(tmp)) {
case T_REGEXP:
{
bool r = rb_reg_start_with_p(tmp, str);
if (r) return Qtrue;
}
break;
default:
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 перечисленных.
"hello".start_with?("hell") #=> 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);
} Возвращает копию str с удалёнными ведущими и хвостовыми пробелами.
Пробелы определяются как любой из следующих символов: null, горизонтальная табуляция, перевод строки, вертикальная табуляция, подача страницы, возврат каретки, пробел.
" hello ".strip #=> "hello" "\tgoodbye\r\n".strip #=> "goodbye" "\x00\t\n\v\f\r ".strip #=> ""
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;
} Удаляет ведущие и хвостовые пробелы из str. Возвращает nil если str не был изменён.
См. strip для определения пробелов.
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 замещённым на второй аргумент. pattern обычно является Regexp; если задан как строка, любые метасимволы регулярных выражений, которые он содержит, будут интерпретироваться буквально, например, '\\d' будет соответствовать обратной косой черте, за которой следует 'd', а не цифре.
Если replacement является строкой, она будет подставлена вместо найденного текста. Она может содержать обратные ссылки на группы захвата шаблона в форме "\d", где d — это номер группы, или "\k<n>", где n — это имя группы. Если это строка в двойных кавычках, обе обратные ссылки должны предшествовать дополнительной обратной косой черте. Однако внутри replacement специальные переменные соответствия, такие как $&, не будут ссылаться на текущее соответствие. Если replacement является строкой, которая выглядит как группа захвата шаблона, но на самом деле не является группой захвата шаблона, например, "\'", то ей придётся предшествовать двум обратным косым чертам, например, "\\'".
Если второй аргумент является Hash, и найденный текст является одним из его ключей, соответствующее значение является строкой замены.
В блочной форме текущая строка соответствия передаётся как параметр, и переменные, такие как $1, $2, $`, $& и $', будут установлены соответствующим образом. Значение, возвращаемое блоком, будет подставлено вместо соответствия при каждом вызове.
Результат наследует любое заражение в исходной строке или любой предоставленной строке замены.
"hello".sub(/[aeiou]/, '*') #=> "h*llo"
"hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo"
"hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello"
"hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo"
'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
#=> "Is /bin/bash your preferred shell?"
static VALUE
rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
{
VALUE pat, repl, hash = Qnil;
int iter = 0;
int tainted = 0;
long plen;
int min_arity = rb_block_given_p() ? 1 : 2;
long beg;
rb_check_arity(argc, min_arity, 2);
if (argc == 1) {
iter = 1;
}
else {
repl = argv[1];
hash = rb_check_hash_type(argv[1]);
if (NIL_P(hash)) {
StringValue(repl);
}
tainted = OBJ_TAINTED_RAW(repl);
}
pat = get_pat_quoted(argv[0], 1);
str_modifiable(str);
beg = rb_pat_search(pat, str, 0, 1);
if (beg >= 0) {
rb_encoding *enc;
int cr = ENC_CODERANGE(str);
long beg0, end0;
VALUE match, match0 = Qnil;
struct re_registers *regs;
char *p, *rp;
long len, rlen;
match = rb_backref_get();
regs = RMATCH_REGS(match);
if (RB_TYPE_P(pat, T_STRING)) {
beg0 = beg;
end0 = beg0 + RSTRING_LEN(pat);
match0 = pat;
}
else {
beg0 = BEG(0);
end0 = END(0);
if (iter) match0 = rb_reg_nth_match(0, match);
}
if (iter || !NIL_P(hash)) {
p = RSTRING_PTR(str); len = RSTRING_LEN(str);
if (iter) {
repl = rb_obj_as_string(rb_yield(match0));
}
else {
repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
repl = rb_obj_as_string(repl);
}
str_mod_check(str, p, len);
rb_check_frozen(str);
}
else {
repl = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
}
enc = rb_enc_compatible(str, repl);
if (!enc) {
rb_encoding *str_enc = STR_ENC_GET(str);
p = RSTRING_PTR(str); len = RSTRING_LEN(str);
if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
rb_enc_name(str_enc),
rb_enc_name(STR_ENC_GET(repl)));
}
enc = STR_ENC_GET(repl);
}
rb_str_modify(str);
rb_enc_associate(str, enc);
tainted |= OBJ_TAINTED_RAW(repl);
if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
int cr2 = ENC_CODERANGE(repl);
if (cr2 == ENC_CODERANGE_BROKEN ||
(cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
cr = ENC_CODERANGE_UNKNOWN;
else
cr = cr2;
}
plen = end0 - beg0;
rp = RSTRING_PTR(repl); rlen = RSTRING_LEN(repl);
len = RSTRING_LEN(str);
if (rlen > plen) {
RESIZE_CAPA(str, len + rlen - plen);
}
p = RSTRING_PTR(str);
if (rlen != plen) {
memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
}
memcpy(p + beg0, rp, rlen);
len += rlen - plen;
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
ENC_CODERANGE_SET(str, cr);
FL_SET_RAW(str, tainted);
return str;
}
return Qnil;
} Выполняет ту же подстановку, что и #sub, на месте.
Возвращает str, если подстановка была выполнена, или nil, если подстановка не была выполнена.
VALUE
rb_str_succ(VALUE orig)
{
VALUE str;
str = rb_str_new_with_class(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
rb_enc_cr_str_copy_for_substr(str, orig);
OBJ_INFECT(str, orig);
return str_succ(str);
} Возвращает следующий за str элемент. Следующий элемент вычисляется путем инкрементирования символов, начиная с крайнего правого буквенно-цифрового (или крайнего правого символа, если буквенно-цифровых нет) в строке. Инкрементирование цифры всегда приводит к другой цифре, а инкрементирование буквы приводит к другой букве того же регистра. Инкрементирование небуквенно-цифровых символов использует кодировку набора символов.
Если инкремент генерирует «перенос», инкрементируется символ слева от него. Этот процесс повторяется до тех пор, пока не будет переноса, при необходимости добавляя дополнительный символ.
"abcd".succ #=> "abce" "THX1138".succ #=> "THX1139" "<<koala>>".succ #=> "<<koalb>>" "1999zzz".succ #=> "2000aaa" "ZZZ9999".succ #=> "AAAA0000" "***".succ #=> "**+"
static VALUE
rb_str_succ_bang(VALUE str)
{
rb_str_modify(str);
str_succ(str);
return str;
} Эквивалентно String#succ, но изменяет получателя на месте.
static VALUE
rb_str_sum(int argc, VALUE *argv, VALUE str)
{
VALUE vbits;
int bits;
char *ptr, *p, *pend;
long len;
VALUE sum = INT2FIX(0);
unsigned long sum0 = 0;
if (argc == 0) {
bits = 16;
}
else {
rb_scan_args(argc, argv, "01", &vbits);
bits = NUM2INT(vbits);
if (bits < 0)
bits = 0;
}
ptr = p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
pend = p + len;
while (p < pend) {
if (FIXNUM_MAX - UCHAR_MAX < sum0) {
sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
str_mod_check(str, ptr, len);
sum0 = 0;
}
sum0 += (unsigned char)*p;
p++;
}
if (bits == 0) {
if (sum0) {
sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
}
}
else {
if (sum == INT2FIX(0)) {
if (bits < (int)sizeof(long)*CHAR_BIT) {
sum0 &= (((unsigned long)1)<<bits)-1;
}
sum = LONG2FIX(sum0);
}
else {
VALUE mod;
if (sum0) {
sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
}
mod = rb_funcall(INT2FIX(1), idLTLT, 1, INT2FIX(bits));
mod = rb_funcall(mod, '-', 1, INT2FIX(1));
sum = rb_funcall(sum, '&', 1, mod);
}
}
return sum;
} Возвращает основную контрольную сумму n-бит символов в str, где n — это необязательный параметр Integer, по умолчанию равный 16. Результат — это просто сумма двоичного значения каждого байта в str по модулю 2**n - 1. Это не очень хорошая контрольная сумма.
static VALUE
rb_str_swapcase(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_swapcase_bang(argc, argv, str);
return str;
} Возвращает копию str с прописными алфавитными символами, преобразованными в строчные, и строчными символами, преобразованными в прописные.
См. #downcase для значения options и использования с различными кодировками.
"Hello".swapcase #=> "hELLO" "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"
static VALUE
rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Эквивалентно String#swapcase, но изменяет получателя на месте, возвращая str или nil, если изменений не было.
См. #downcase для значения options и использования с различными кодировками.
static VALUE
rb_str_to_f(VALUE str)
{
return DBL2NUM(rb_str_to_dbl(str, FALSE));
} Возвращает результат интерпретации начальных символов в str как числа с плавающей точкой. Лишние символы после конца допустимого числа игнорируются. Если в начале str нет допустимого числа, возвращается 0.0. Этот метод никогда не вызывает исключения.
"123.45e1".to_f #=> 1234.5 "45.67 degrees".to_f #=> 45.67 "thx1138".to_f #=> 0.0
static VALUE
rb_str_to_i(int argc, VALUE *argv, VALUE str)
{
int base;
if (argc == 0) base = 10;
else {
VALUE b;
rb_scan_args(argc, argv, "01", &b);
base = NUM2INT(b);
}
if (base < 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);
if (RB_FLOAT_TYPE_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.
static VALUE
rb_str_to_s(VALUE str)
{
if (rb_obj_class(str) != rb_cString) {
return str_duplicate(rb_cString, str);
}
return str;
} Возвращает self.
При вызове из подкласса String преобразует получателя в объект String.
static VALUE
rb_str_to_s(VALUE str)
{
if (rb_obj_class(str) != rb_cString) {
return str_duplicate(rb_cString, str);
}
return str;
} Возвращает self.
При вызове из подкласса String преобразует получателя в объект String.
VALUE
rb_str_intern(VALUE str)
{
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
int type;
#else
ID id;
#endif
VALUE sym = lookup_str_sym(str);
if (sym) {
return sym;
}
#if USE_SYMBOL_GC
enc = rb_enc_get(str);
ascii = rb_usascii_encoding();
if (enc != ascii && sym_check_asciionly(str)) {
str = rb_str_dup(str);
rb_enc_associate(str, ascii);
OBJ_FREEZE(str);
enc = ascii;
}
else {
str = rb_str_new_frozen(str);
}
str = rb_fstring(str);
type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
if (type < 0) type = ID_JUNK;
return dsymbol_alloc(rb_cSymbol, str, enc, type);
#else
id = intern_str(str, 0);
return ID2SYM(id);
#endif
} Возвращает Symbol, соответствующий str, создавая символ, если он ранее не существовал. См. Symbol#id2name.
"Koala".intern #=> :Koala s = 'cat'.to_sym #=> :cat s == :cat #=> true s = '@cat'.to_sym #=> :@cat s == :@cat #=> true
Это также может использоваться для создания символов, которые не могут быть представлены с помощью обозначения :xxx.
'cat and dog'.to_sym #=> :"cat and dog"
static VALUE
rb_str_tr(VALUE str, VALUE src, VALUE repl)
{
str = rb_str_dup(str);
tr_trans(str, src, repl, 0);
return str;
} Возвращает копию str с символами в from_str, заменёнными на соответствующие символы в to_str. Если to_str короче, чем from_str, он дополняется его последним символом, чтобы сохранить соответствие.
"hello".tr('el', 'ip') #=> "hippo"
"hello".tr('aeiou', '*') #=> "h*ll*"
"hello".tr('aeiou', 'AA*') #=> "hAll*"
Обе строки могут использовать обозначение c1-c2 для обозначения диапазонов символов, и from_str может начинаться с ^, что обозначает все символы, кроме указанных.
"hello".tr('a-y', 'b-z') #=> "ifmmp"
"hello".tr('^aeiou', '*') #=> "*e**o"
Символ обратной косой черты \ может использоваться для экранирования ^ или - и в противном случае игнорируется, если только он не появляется в конце диапазона или в конце from_str или to_str:
"hello^world".tr("\\^aeiou", "*") #=> "h*ll**w*rld"
"hello-world".tr("a\\-eo", "*") #=> "h*ll**w*rld"
"hello\r\nworld".tr("\r", "") #=> "hello\nworld"
"hello\r\nworld".tr("\\r", "") #=> "hello\r\nwold"
"hello\r\nworld".tr("\\\r", "") #=> "hello\nworld"
"X['\\b']".tr("X\\", "") #=> "['b']"
"X['\\b']".tr("X-\\]", "") #=> "'b'"
static VALUE
rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
{
return tr_trans(str, src, repl, 0);
} Производит замену символов в строке str на месте, используя те же правила, что и String#tr. Возвращает str или nil , если изменений не произошло.
static VALUE
rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
{
str = rb_str_dup(str);
tr_trans(str, src, repl, 1);
return str;
} Обрабатывает копию str, как описано в String#tr, а затем удаляет повторяющиеся символы в регионах, затронутых переводом.
"hello".tr_s('l', 'r') #=> "hero"
"hello".tr_s('el', '*') #=> "h*o"
"hello".tr_s('el', 'hx') #=> "hhxo"
static VALUE
rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
{
return tr_trans(str, src, repl, 1);
} Производит обработку на месте str, как описано в String#tr_s, возвращая 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 {
const char *encname;
int encidx;
ptrdiff_t size;
if (utf8) {
rb_raise(rb_eRuntimeError, "dumped string contained Unicode escape but used force_encoding");
}
size = rb_strlen_lit(".force_encoding(\"");
if (s_end - s <= size) goto invalid_format;
if (memcmp(s, ".force_encoding(\"", size) != 0) goto invalid_format;
s += size;
encname = s;
s = memchr(s, '"', s_end-s);
size = s - encname;
if (!s) goto invalid_format;
if (s_end - s != 2) goto invalid_format;
if (s[0] != '"' || s[1] != ')') goto invalid_format;
encidx = rb_enc_find_index2(encname, (long)size);
if (encidx < 0) {
rb_raise(rb_eRuntimeError, "dumped string has unknown encoding name");
}
rb_enc_associate_index(undumped, encidx);
}
break;
}
if (*s == '\\') {
s++;
if (s >= s_end) {
rb_raise(rb_eRuntimeError, "invalid escape");
}
undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
}
else {
rb_str_cat(undumped, s++, 1);
}
}
OBJ_INFECT(undumped, str);
return undumped;
invalid_format:
rb_raise(rb_eRuntimeError, "invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
} Возвращает строку без экранирования str. См. также #dump, так как #undump производит обратное преобразование по отношению к #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));
} Деструктивная версия #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. Для получения более подробной информации см. #unicode_normalize.
"a\u0300".unicode_normalized? #=> false
"a\u0300".unicode_normalized?(:nfd) #=> true
"\u00E0".unicode_normalized? #=> true
"\u00E0".unicode_normalized?(:nfd) #=> false
"\xE0".force_encoding('ISO-8859-1').unicode_normalized?
#=> Encoding::CompatibilityError raised
static VALUE
pack_unpack(VALUE str, VALUE fmt)
{
int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY;
return pack_unpack_internal(str, fmt, mode);
} Декодирует str (которая может содержать двоичные данные) согласно строке формата, возвращая массив из каждого извлеченного значения. Строка формата состоит из последовательности директив из одного символа, резюмированных в таблице в конце этого раздела. Каждая директива может быть последовать числом, указывающим количество повторений с данной директивой. Звёздочка («*») использует все оставшиеся элементы. Директивы sSiIlL могут быть дополнены подчёркиванием («_») или восклицательным знаком («!») для использования размера по умолчанию для указанного типа; в противном случае используется независимый от платформы размер. Пробелы в строке формата игнорируются. См. также String#unpack1, Array#pack.
"abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
"abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
"abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
"aa".unpack('b8B8') #=> ["10000110", "01100001"]
"aaa".unpack('h2H2c') #=> ["16", "61", 97]
"\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
"now=20is".unpack('M*') #=> ["now is"]
"whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
В этой таблице резюмированы различные форматы и классы Ruby, возвращаемые каждым.
Integer | |
Directive | Returns | Meaning
------------------------------------------------------------------
C | Integer | 8-bit unsigned (unsigned char)
S | Integer | 16-bit unsigned, native endian (uint16_t)
L | Integer | 32-bit unsigned, native endian (uint32_t)
Q | Integer | 64-bit unsigned, native endian (uint64_t)
J | Integer | pointer width unsigned, native endian (uintptr_t)
| |
c | Integer | 8-bit signed (signed char)
s | Integer | 16-bit signed, native endian (int16_t)
l | Integer | 32-bit signed, native endian (int32_t)
q | Integer | 64-bit signed, native endian (int64_t)
j | Integer | pointer width signed, native endian (intptr_t)
| |
S_ S! | Integer | unsigned short, native endian
I I_ I! | Integer | unsigned int, native endian
L_ L! | Integer | unsigned long, native endian
Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
| | if the platform has no long long type.)
J! | Integer | uintptr_t, native endian (same with J)
| |
s_ s! | Integer | signed short, native endian
i i_ i! | Integer | signed int, native endian
l_ l! | Integer | signed long, native endian
q_ q! | Integer | signed long long, native endian (ArgumentError
| | if the platform has no long long type.)
j! | Integer | intptr_t, native endian (same with j)
| |
S> s> S!> s!> | Integer | same as the directives without ">" except
L> l> L!> l!> | | big endian
I!> i!> | |
Q> q> Q!> q!> | | "S>" is same as "n"
J> j> J!> j!> | | "L>" is same as "N"
| |
S< s< S!< s!< | Integer | same as the directives without "<" except
L< l< L!< l!< | | little endian
I!< i!< | |
Q< q< Q!< q!< | | "S<" is same as "v"
J< j< J!< j!< | | "L<" is same as "V"
| |
n | Integer | 16-bit unsigned, network (big-endian) byte order
N | Integer | 32-bit unsigned, network (big-endian) byte order
v | Integer | 16-bit unsigned, VAX (little-endian) byte order
V | Integer | 32-bit unsigned, VAX (little-endian) byte order
| |
U | Integer | UTF-8 character
w | Integer | BER-compressed integer (see Array.pack)
Float | |
Directive | Returns | Meaning
-----------------------------------------------------------------
D d | Float | double-precision, native format
F f | Float | single-precision, native format
E | Float | double-precision, little-endian byte order
e | Float | single-precision, little-endian byte order
G | Float | double-precision, network (big-endian) byte order
g | Float | single-precision, network (big-endian) byte order
String | |
Directive | Returns | Meaning
-----------------------------------------------------------------
A | String | arbitrary binary string (remove trailing nulls and ASCII spaces)
a | String | arbitrary binary string
Z | String | null-terminated string
B | String | bit string (MSB first)
b | String | bit string (LSB first)
H | String | hex string (high nibble first)
h | String | hex string (low nibble first)
u | String | UU-encoded string
M | String | quoted-printable, MIME encoding (see RFC2045)
m | String | base64 encoded string (RFC 2045) (default)
| | base64 encoded string (RFC 4648) if followed by 0
P | String | pointer to a structure (fixed-length string)
p | String | pointer to a null-terminated string
Misc. | |
Directive | Returns | Meaning
-----------------------------------------------------------------
@ | --- | skip to the offset given by the length argument
X | --- | skip backward one byte
x | --- | skip forward one byte ИСТОРИЯ
-
J, J! j, и j! доступны начиная с Ruby 2.3.
-
Q_, Q!, q_, и q! доступны начиная с Ruby 2.1.
-
I!<, i!<, I!>, и i!> доступны начиная с Ruby 1.9.3.
static VALUE
pack_unpack1(VALUE str, VALUE fmt)
{
return pack_unpack_internal(str, fmt, UNPACK_1);
} Декодирует str (которая может содержать двоичные данные) согласно строке формата, возвращая первое извлеченное значение. См. также String#unpack, Array#pack.
static VALUE
rb_str_upcase(int argc, VALUE *argv, VALUE str)
{
str = rb_str_dup(str);
rb_str_upcase_bang(argc, argv, str);
return str;
} Возвращает копию str с заменой всех строчных букв на заглавные.
См. #downcase для значения options и использования с разными кодировками.
"hEllO".upcase #=> "HELLO"
static VALUE
rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
flags = check_case_options(argc, argv, flags);
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (((flags&ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() || rb_enc_mbmaxlen(enc)==1))
|| (!(flags&ONIGENC_CASE_FOLD_TURKISH_AZERI) && ENC_CODERANGE(str)==ENC_CODERANGE_7BIT)) {
char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
while (s < send) {
unsigned int c = *(unsigned char*)s;
if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
*s = 'A' + (c - 'a');
flags |= ONIGENC_CASE_MODIFIED;
}
s++;
}
}
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, &flags, enc);
else
str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
} Преобразует содержимое str в заглавные буквы, возвращая nil , если изменений не произошло.
См. #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 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 содержат только символы арифметических значений ASCII, оба распознаются как десятичные числа. Кроме того, ширина строки (например, ведущие нули) обрабатывается должным образом.
"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.