Spec-Zone.ru › Ruby 4.0

класс String

Родительский класс:
Object
Подключённые модули:
Comparable

Объект String содержит произвольную последовательность байтов, обычно представляющую текст или двоичные данные. Объект String можно создать с помощью String::new или в виде литерала.

Объекты String отличаются от объектов Symbol тем, что объекты Symbol предназначены для использования в качестве идентификаторов, а не текста или данных.

Создать объект String явно можно с помощью:

  • строкового литерала.

  • литерала heredoc.

Некоторые объекты можно преобразовать в строки с помощью:

  • Метода String.

Некоторые методы String изменяют self. Обычно метод, имя которого заканчивается на !, изменяет self и возвращает self; часто одноимённый метод (без !) возвращает новую строку.

Как правило, если у метода есть версии с восклицательным знаком и без него, метод с восклицательным знаком изменяет объект, а метод без него — нет. Однако метод без восклицательного знака тоже может изменять объект, например String#replace.

Методы подстановки

Эти методы выполняют подстановки:

  • String#sub: одна подстановка (или ни одной); возвращает новую строку.

  • String#sub!: одна подстановка (или ни одной); возвращает self, если были изменения, и nil в противном случае.

  • String#gsub: ноль или более подстановок; возвращает новую строку.

  • String#gsub!: ноль или более подстановок; возвращает self, если были изменения, и nil в противном случае.

Каждый из этих методов принимает:

  • Первый аргумент, pattern (String или Regexp), который указывает подстроку (или подстроки), подлежащую замене.

  • Один из следующих вариантов:

    • Второй аргумент, replacement (String или Hash), определяющий строку замены.

    • Блок, который определяет строку замены.

В примерах этого раздела в основном используются методы String#sub и String#gsub; описанные принципы применимы ко всем четырём методам подстановки.

Аргумент pattern

Аргумент pattern обычно является регулярным выражением:

s = 'hello'
s.sub(/[aeiou]/, '*') # => "h*llo"
s.gsub(/[aeiou]/, '*') # => "h*ll*"
s.gsub(/[aeiou]/, '')  # => "hll"
s.sub(/ell/, 'al')     # => "halo"
s.gsub(/xyzzy/, '*')   # => "hello"
'THX1138'.gsub(/\d+/, '00') # => "THX00"

Если pattern — строка, все её символы трактуются как обычные символы (а не как специальные символы Regexp):

'THX1138'.gsub('\d+', '00') # => "THX1138"

String replacement

Если replacement — строка, она определяет строку замены, которой подменяется совпавший текст.

Во всех приведённых выше примерах в качестве строки замены используется простая строка.

String replacement может содержать обратные ссылки на захваты шаблона:

  • \n (где n — неотрицательное целое число) ссылается на $n.

  • \k<name> ссылается на именованный захват name.

Подробности см. в разделе Regexp.

Обратите внимание: в строке replacement комбинация символов, например $&, трактуется как обычный текст, а не как специальная переменная совпадения. Однако на некоторые специальные переменные совпадения можно ссылаться с помощью следующих комбинаций:

  • \& и \0 соответствуют $&, содержащей весь совпавший текст.

  • \' соответствует $', содержащей строку после совпадения.

  • \` соответствует $`, содержащей строку перед совпадением.

  • \+ соответствует $+, содержащей последнюю группу захвата.

Подробности см. в разделе Regexp.

Обратите внимание, что \\ интерпретируется как экранирующий символ, то есть как одна обратная косая черта.

Также обратите внимание, что строковый литерал поглощает обратные косые черты. Подробности о строковых литералах см. в разделе Строковые литералы.

Перед обратной ссылкой обычно ставится дополнительная обратная косая черта. Например, если вы хотите записать обратную ссылку \& в replacement с помощью строкового литерала в двойных кавычках, необходимо написать "..\\&..".

Если вы хотите записать строку, не являющуюся обратной ссылкой, \& в replacement, сначала нужно экранировать обратную косую черту, чтобы этот метод не интерпретировал её как обратную ссылку, а затем ещё раз экранировать обратные косые черты, чтобы строковый литерал их не поглотил: "..\\\\&..".

Чтобы избежать чрезмерного количества обратных косых черт, можно использовать форму с блоком.

Хеш replacement

Если аргумент replacement — хеш и pattern совпадает с одним из его ключей, в качестве строки замены используется значение, соответствующее этому ключу:

h = {'foo' => 'bar', 'baz' => 'bat'}
'food'.sub('foo', h) # => "bard"

Обратите внимание: ключ-символ не даёт совпадения:

h = {foo: 'bar', baz: 'bat'}
'food'.sub('foo', h) # => "d"

Блок

В форме с блоком текущая строка совпадения передаётся блоку; возвращаемое блоком значение становится строкой замены:

s = '@'
'1234'.gsub(/\d/) { |match| s.succ! } # => "ABCD"

Специальные переменные совпадения, такие как $1, $2, $`, $& и $', получают соответствующие значения.

Пробельные символы в строках

В классе String пробельные символы определяются как непрерывная последовательность символов, состоящая из любых комбинаций следующих элементов:

  • NL (нулевой символ): "\x00", "\u0000".

  • HT (горизонтальная табуляция): "\x09", "\t".

  • LF (перевод строки): "\x0a", "\n".

  • VT (вертикальная табуляция): "\x0b", "\v".

  • FF (перевод страницы): "\x0c", "\f".

  • CR (возврат каретки): "\x0d", "\r".

  • SP (пробел): "\x20", " ".

Пробельные символы используются в следующих методах:

  • lstrip, lstrip!: удаление пробельных символов в начале строки.

  • rstrip, rstrip!: удаление пробельных символов в конце строки.

  • strip, strip!: удаление пробельных символов в начале и конце строки.

Что здесь находится

Сначала — что находится в других разделах. Класс String:

  • Наследуется от класса Object.

  • Подключает модуль Comparable.

В этом разделе класс String предоставляет методы для:

  • создания строки.

  • заморозки и разморозки строки.

  • получения сведений о строке.

  • сравнения строк.

  • изменения строки.

  • преобразования в новую строку.

  • преобразования в объект, не являющийся строкой.

  • перебора строки.

Создание строки

  • ::new: возвращает новую строку.

  • ::try_convert: возвращает новую строку, созданную из заданного объекта.

Заморозка и разморозка

  • +@: возвращает незамороженную строку: self, если строка не заморожена; в противном случае — self.dup.

  • -@ (имеет псевдоним dedup): возвращает замороженную строку: self, если строка уже заморожена; в противном случае — self.freeze.

  • freeze: замораживает self, если она ещё не заморожена; возвращает self.

Получение сведений

Количество

  • bytesize: возвращает количество байтов.

  • count: возвращает количество подстрок, совпадающих с заданными строками.

  • empty?: возвращает значение, указывающее, равна ли длина self нулю.

  • length (имеет псевдоним size): возвращает количество символов (не байтов).

Подстроки

  • =~: возвращает индекс первой подстроки, совпавшей с заданным Regexp или другим объектом; если совпадение не найдено, возвращает nil.

  • byteindex: возвращает байтовый индекс первого вхождения заданной подстроки.

  • byterindex: возвращает байтовый индекс последнего вхождения заданной подстроки.

  • index: возвращает индекс первого вхождения заданной подстроки; если совпадений нет, возвращает nil.

  • rindex: возвращает индекс последнего вхождения заданной подстроки; если совпадений нет, возвращает nil.

  • include?: возвращает true, если строка содержит заданную подстроку; в противном случае — false.

  • match: возвращает объект MatchData, если строка соответствует заданному Regexp; в противном случае — nil.

  • match?: возвращает true, если строка соответствует заданному Regexp; в противном случае — false.

  • start_with?: возвращает true, если строка начинается с любой из заданных подстрок.

  • end_with?: возвращает true, если строка заканчивается любой из заданных подстрок.

Кодировки

  • encoding: возвращает объект Encoding, представляющий кодировку строки.

  • unicode_normalized?: возвращает true, если строка находится в нормализованной форме Unicode; в противном случае — false.

  • valid_encoding?: возвращает true, если строка содержит только символы, допустимые для её кодировки.

  • ascii_only?: возвращает true, если строка содержит только символы ASCII; в противном случае — false.

Прочее

  • sum: возвращает простую контрольную сумму строки — сумму значений всех байтов.

  • hash: возвращает целочисленный хеш-код.

Сравнение

  • == (также известен как ===): Возвращает true, если заданная другая строка имеет то же содержимое, что и self.

  • eql?: Возвращает true, если содержимое совпадает с содержимым заданной другой строки.

  • <=>: Возвращает -1, 0 или 1 в зависимости от того, меньше ли заданная другая строка, равна ли или больше self.

  • casecmp: Без учета регистра возвращает -1, 0 или 1 в зависимости от того, меньше ли self, равна ли или больше заданной другой строки.

  • casecmp?: Без учета регистра возвращает, равна ли заданная другая строка self.

Изменение

Каждый из этих методов изменяет self.

Вставка

  • insert: Возвращает self со вставленной в указанную позицию заданной строкой.

  • <<: Возвращает self, объединённую с заданной строкой или целым числом.

  • append_as_bytes: Возвращает self, объединённую со строками без проверки или преобразования кодировки.

  • prepend: Добавляет в начало self объединение заданных других строк.

Замена

  • bytesplice: Заменяет байты self байтами из заданной строки; возвращает self.

  • sub!: Заменяет первую подстроку, соответствующую заданному шаблону, заданной строкой-заменой; возвращает self, если были внесены изменения, и nil в противном случае.

  • gsub!: Заменяет каждую подстроку, соответствующую заданному шаблону, заданной строкой-заменой; возвращает self, если были внесены изменения, и nil в противном случае.

  • succ! (также известен как next!): Возвращает self, изменённую так, чтобы она стала своим собственным преемником.

  • replace: Возвращает self, полностью заменив её содержимое заданной строкой.

  • reverse!: Возвращает self с символами в обратном порядке.

  • setbyte: Устанавливает заданное значение для байта по заданному целочисленному смещению; возвращает аргумент.

  • tr!: Заменяет указанные символы в self указанными символами-заменами; возвращает self, если были внесены изменения, и nil в противном случае.

  • tr_s!: Заменяет указанные символы в self указанными символами-заменами, удаляя дубликаты из изменённых подстрок; возвращает self, если были внесены изменения, и nil в противном случае.

Регистр

  • capitalize!: Переводит первый символ в верхний регистр, а все остальные — в нижний; возвращает self, если были внесены изменения, и nil в противном случае.

  • downcase!: Переводит все символы в нижний регистр; возвращает self, если были внесены изменения, и nil в противном случае.

  • upcase!: Переводит все символы в верхний регистр; возвращает self, если были внесены изменения, и nil в противном случае.

  • swapcase!: Переводит каждый символ в нижнем регистре в верхний, а каждый символ в верхнем регистре — в нижний; возвращает self, если были внесены изменения, и nil в противном случае.

Кодировка

  • encode!: Возвращает self, в которой все символы преобразованы из одной кодировки в другую.

  • unicode_normalize!: Выполняет нормализацию Unicode для self; возвращает self.

  • scrub!: Заменяет каждый недопустимый байт заданным символом; возвращает self.

  • force_encoding: Изменяет кодировку на заданную; возвращает self.

Удаление

  • clear: Удаляет всё содержимое, оставляя self пустой; возвращает self.

  • slice!, []=: Удаляет подстроку, определяемую заданным индексом, начальной позицией и длиной, диапазоном, регулярным выражением или подстрокой.

  • squeeze!: Удаляет подряд идущие повторяющиеся символы; возвращает self.

  • delete!: Удаляет символы, определяемые пересечением аргументов-подстрок.

  • delete_prefix!: Удаляет начальный префикс; возвращает self, если были внесены изменения, и nil в противном случае.

  • delete_suffix!: Удаляет конечный суффикс; возвращает self, если были внесены изменения, и nil в противном случае.

  • lstrip!: Удаляет начальные пробельные символы; возвращает self, если были внесены изменения, и nil в противном случае.

  • rstrip!: Удаляет конечные пробельные символы; возвращает self, если были внесены изменения, и nil в противном случае.

  • strip!: Удаляет начальные и конечные пробельные символы; возвращает self, если были внесены изменения, и nil в противном случае.

  • chomp!: Удаляет конечный разделитель записей, если он найден; возвращает self, если были внесены изменения, и nil в противном случае.

  • chop!: Удаляет конечные символы новой строки, если они найдены; в противном случае удаляет последний символ; возвращает self, если были внесены изменения, и nil в противном случае.

Преобразование в новую строку

Каждый из этих методов возвращает новую String на основе self, часто просто изменённую копию self.

Расширение

  • *: Возвращает объединение нескольких копий self.

  • +: Возвращает объединение self и заданной другой строки.

  • center: Возвращает копию self, выровненную по центру с указанными символами-заполнителями.

  • concat: Возвращает объединение self с заданными другими строками.

  • ljust: Возвращает копию self заданной длины, дополненную справа заданной другой строкой.

  • rjust: Возвращает копию self заданной длины, дополненную слева заданной другой строкой.

Кодировка

  • b: Возвращает копию self с кодировкой ASCII-8BIT.

  • scrub: Возвращает копию self, в которой каждый недопустимый байт заменён заданным символом.

  • unicode_normalize: Возвращает копию self, в которой каждый символ нормализован по Unicode.

  • encode: Возвращает копию self, в которой все символы преобразованы из одной кодировки в другую.

Замена

  • dump: Возвращает печатное представление self, заключённое в двойные кавычки.

  • undump: Обратная операция для dump; возвращает копию self, в которой отменены изменения, подобные тем, что выполняет dump.

  • sub: Возвращает копию self, в которой первая подстрока, соответствующая заданному шаблону, заменена заданной строкой-заменой.

  • gsub: Возвращает копию self, в которой каждая подстрока, соответствующая заданному шаблону, заменена заданной строкой-заменой.

  • succ (также известен как next): Возвращает строку, следующую за self.

  • reverse: Возвращает копию self с символами в обратном порядке.

  • tr: Возвращает копию self, в которой указанные символы заменены указанными символами-заменами.

  • tr_s: Возвращает копию self, в которой указанные символы заменены указанными символами-заменами, а из изменённых подстрок удалены дубликаты.

  • %: Возвращает строку, полученную в результате форматирования заданного объекта в self.

Регистр

  • capitalize: Возвращает копию self, в которой первый символ переведён в верхний регистр, а все остальные — в нижний.

  • downcase: Возвращает копию self, в которой все символы переведены в нижний регистр.

  • upcase: Возвращает копию self, в которой все символы переведены в верхний регистр.

  • swapcase: Возвращает копию self, в которой все символы в верхнем регистре переведены в нижний, а все символы в нижнем регистре — в верхний.

Удаление

  • delete: Возвращает копию self с удалёнными символами.

  • delete_prefix: Возвращает копию self с удалённым заданным префиксом.

  • delete_suffix: Возвращает копию self с удалённым заданным суффиксом.

  • lstrip: Возвращает копию self с удалёнными начальными пробельными символами.

  • rstrip: Возвращает копию self с удалёнными конечными пробельными символами.

  • strip: Возвращает копию self с удалёнными начальными и конечными пробельными символами.

  • chomp: Возвращает копию self с удалённым конечным разделителем записей, если он найден.

  • chop: Возвращает копию self с удалёнными конечными символами новой строки или последним символом.

  • squeeze: Возвращает копию self с удалёнными подряд идущими повторяющимися символами.

  • [] (также известен как slice): Возвращает подстроку, определяемую заданным индексом, начальной позицией и длиной, диапазоном, регулярным выражением или строкой.

  • byteslice: Возвращает подстроку, определяемую заданным индексом, начальной позицией и длиной или диапазоном.

  • chr: Возвращает первый символ.

Дублирование

  • to_s (также известен как to_str): Если self является подклассом String, возвращает self, скопированную в String; в противном случае возвращает self.

Преобразование в объект не типа String

Каждый из этих методов преобразует содержимое self в объект не типа String.

Символы, байты и кластеры

  • bytes: Возвращает массив байтов в self.

  • chars: Возвращает массив символов в self.

  • codepoints: Возвращает массив целочисленных кодовых точек в self.

  • getbyte: Возвращает целочисленное значение байта по заданному индексу в self.

  • grapheme_clusters: Возвращает массив графемных кластеров в self.

Разбиение

  • lines: Возвращает массив строк в self, определяемых заданным разделителем записей.

  • partition: Возвращает массив из 3 элементов, определяемый первой подстрокой, соответствующей заданной подстроке или регулярному выражению.

  • rpartition: Возвращает массив из 3 элементов, определяемый последней подстрокой, соответствующей заданной подстроке или регулярному выражению.

  • split: Возвращает массив подстрок, разделённых заданным разделителем — регулярным выражением или строкой, — либо передаёт эти подстроки блоку, если он задан.

Сопоставление

  • scan: Возвращает массив подстрок, соответствующих заданному регулярному выражению или строке, либо передаёт каждую совпавшую подстроку блоку, если он задан.

  • unpack: Возвращает массив подстрок, извлечённых из self согласно заданному формату.

  • unpack1: Возвращает первую подстроку, извлечённую из self согласно заданному формату.

Числовые значения

  • hex: Возвращает целочисленное значение начальных символов, интерпретируемых как шестнадцатеричные цифры.

  • oct: Возвращает целочисленное значение начальных символов, интерпретируемых как восьмеричные цифры.

  • ord: Возвращает целочисленный код первой буквы в self.

  • to_c: Возвращает комплексное значение начальных символов, интерпретируемых как комплексное число.

  • to_i: Возвращает целочисленное значение начальных символов, интерпретируемых как целое число.

  • to_f: Возвращает значение с плавающей точкой начальных символов, интерпретируемых как число с плавающей точкой.

  • to_r: Возвращает рациональное значение начальных символов, интерпретируемых как рациональное число.

Строки и символы

  • inspect: Возвращает копию self, заключённую в двойные кавычки, со специальными символами, представленными escape-последовательностями.

  • intern (также доступен под именем to_sym): Возвращает символ, соответствующий self.

Итерация

  • each_byte: Вызывает заданный блок для каждого следующего байта в self.

  • each_char: Вызывает заданный блок для каждого следующего символа в self.

  • each_codepoint: Вызывает заданный блок для каждой следующей целочисленной кодовой точки в self.

  • each_grapheme_cluster: Вызывает заданный блок для каждого следующего графемного кластера в self.

  • each_line: Вызывает заданный блок для каждой следующей строки в self, определяемой заданным разделителем записей.

  • upto: Вызывает заданный блок для каждого строкового значения, возвращаемого последовательными вызовами succ.

Открытые методы класса

json_create(o) Показать исходный код
# File ext/json/lib/json/add/string.rb, line 11
def self.json_create(object)
  object["raw"].pack("C*")
end

Необработанные строки являются объектами JSON (необработанные байты хранятся в массиве под ключом «raw»). Строку Ruby String можно создать с помощью этого метода класса.

new(string = ''.encode(Encoding::ASCII_8BIT) , **options) → new_string Показать исходный код
static VALUE
rb_str_init(int argc, VALUE *argv, VALUE str)
{
    static ID keyword_ids[2];
    VALUE orig, opt, venc, vcapa;
    VALUE kwargs[2];
    rb_encoding *enc = 0;
    int n;

    if (!keyword_ids[0]) {
        keyword_ids[0] = rb_id_encoding();
        CONST_ID(keyword_ids[1], "capacity");
    }

    n = rb_scan_args(argc, argv, "01:", &orig, &opt);
    if (!NIL_P(opt)) {
        rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
        venc = kwargs[0];
        vcapa = kwargs[1];
        if (!UNDEF_P(venc) && !NIL_P(venc)) {
            enc = rb_to_encoding(venc);
        }
        if (!UNDEF_P(vcapa) && !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) || FL_TEST(str, STR_SHARED|STR_NOFREE)) {
                /* make noembed always */
                const size_t size = (size_t)capa + termlen;
                const char *const old_ptr = RSTRING_PTR(str);
                const size_t osize = RSTRING_LEN(str) + TERM_LEN(str);
                char *new_ptr = ALLOC_N(char, size);
                if (STR_EMBED_P(str)) RUBY_ASSERT((long)osize <= str_embed_capa(str));
                memcpy(new_ptr, old_ptr, osize < size ? osize : size);
                FL_UNSET_RAW(str, STR_SHARED|STR_NOFREE);
                RSTRING(str)->as.heap.ptr = new_ptr;
            }
            else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
                SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
                        (size_t)capa + termlen, STR_HEAP_SIZE(str));
            }
            STR_SET_LEN(str, 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;
}

Возвращает новый объект String, содержащий заданную string.

Параметр options — это необязательные именованные параметры (см. ниже).

Если аргумент не задан и именованный параметр encoding также не задан, возвращается пустая строка с ASCII-8BIT Encoding:

s = String.new # => ""
s.encoding     # => #<Encoding:ASCII-8BIT>

Если задан аргумент string, а именованный параметр encoding не задан, возвращается новая строка с той же кодировкой, что и у string:

s0 = 'foo'.encode(Encoding::UTF_16)
s1 = String.new(s0)
s1.encoding # => #<Encoding:UTF-16 (dummy)>

(В отличие от String.new, строковый литерал, например '', или литерал here-документа всегда имеет кодировку скрипта.)

Если задан именованный параметр encoding, возвращается строка с указанной кодировкой; encoding может быть объектом Encoding, названием кодировки или псевдонимом её названия:

String.new(encoding: Encoding::US_ASCII).encoding        # => #<Encoding:US-ASCII>
String.new('', encoding: Encoding::US_ASCII).encoding    # => #<Encoding:US-ASCII>
String.new('foo', encoding: Encoding::US_ASCII).encoding # => #<Encoding:US-ASCII>
String.new('foo', encoding: 'US-ASCII').encoding         # => #<Encoding:US-ASCII>
String.new('foo', encoding: 'ASCII').encoding            # => #<Encoding:US-ASCII>

Указанная кодировка не обязана соответствовать содержимому строки, и её соответствие не проверяется:

s = String.new('こんにちは', encoding: 'ascii')
s.valid_encoding? # => false

Однако сам параметр encoding проверяется:

String.new('foo', encoding: 'bar') # Raises ArgumentError.

Если задан именованный параметр capacity, указанное значение носит рекомендательный характер и может как повлиять, так и не повлиять на размер внутреннего буфера, что, в свою очередь, может сказаться на производительности:

String.new('foo', capacity: 1)    # Buffer size is at least 4 (includes terminal null byte).
String.new('foo', capacity: 4096) # Buffer size is at least 4;
                                  # may be equal to, greater than, or less than 4096.
try_convert(object) → object, new_string, or nil Показать исходный код
static VALUE
rb_str_s_try_convert(VALUE dummy, VALUE str)
{
    return rb_check_string_type(str);
}

Пытается преобразовать заданный object в строку.

Если object уже является строкой, возвращает object без изменений.

В противном случае, если object отвечает на :to_str, вызывает object.to_str и возвращает результат.

Возвращает nil, если object не отвечает на :to_str.

Вызывает исключение, если object.to_str не возвращает строку.

Открытые методы экземпляра

self % object → new_string Показать исходный код
static VALUE
rb_str_format_m(VALUE str, VALUE arg)
{
    VALUE tmp = rb_check_array_type(arg);

    if (!NIL_P(tmp)) {
        return rb_str_format(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp), str);
    }
    return rb_str_format(1, &arg, str);
}

Возвращает результат форматирования object согласно спецификациям формата, содержащимся в self (см. Спецификации формата):

'%05d' % 123 # => "00123"

Если self содержит несколько спецификаций формата, object должен быть массивом или хешем, содержащим форматируемые объекты:

'%-5s: %016x' % [ 'ID', self.object_id ]                # => "ID   : 00002b054ec93168"
'foo = %{foo}' % {foo: 'bar'}                           # => "foo = bar"
'foo = %{foo}, baz = %{baz}' % {foo: 'bar', baz: 'bat'} # => "foo = bar, baz = bat"

Связанный раздел: см. Преобразование в новую строку.

self * n → new_string Показать исходный код
VALUE
rb_str_times(VALUE str, VALUE times)
{
    VALUE str2;
    long n, len;
    char *ptr2;
    int termlen;

    if (times == INT2FIX(1)) {
        return str_duplicate(rb_cString, str);
    }
    if (times == INT2FIX(0)) {
        str2 = str_alloc_embed(rb_cString, 0);
        rb_enc_copy(str2, str);
        return str2;
    }
    len = NUM2LONG(times);
    if (len < 0) {
        rb_raise(rb_eArgError, "negative argument");
    }
    if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
        if (STR_EMBEDDABLE_P(len, 1)) {
            str2 = str_alloc_embed(rb_cString, len + 1);
            memset(RSTRING_PTR(str2), 0, len + 1);
        }
        else {
            str2 = str_alloc_heap(rb_cString);
            RSTRING(str2)->as.heap.aux.capa = len;
            RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
        }
        STR_SET_LEN(str2, len);
        rb_enc_copy(str2, str);
        return str2;
    }
    if (len && LONG_MAX/len <  RSTRING_LEN(str)) {
        rb_raise(rb_eArgError, "argument too big");
    }

    len *= RSTRING_LEN(str);
    termlen = TERM_LEN(str);
    str2 = str_enc_new(rb_cString, 0, len, STR_ENC_GET(str));
    ptr2 = RSTRING_PTR(str2);
    if (len) {
        n = RSTRING_LEN(str);
        memcpy(ptr2, RSTRING_PTR(str), n);
        while (n <= len/2) {
            memcpy(ptr2 + n, ptr2, n);
            n *= 2;
        }
        memcpy(ptr2 + n, ptr2, len-n);
    }
    STR_SET_LEN(str2, len);
    TERM_FILL(&ptr2[len], termlen);
    rb_enc_cr_str_copy_for_substr(str2, str);

    return str2;
}

Возвращает новую строку, содержащую n копий self:

'Ho!' * 3 # => "Ho!Ho!Ho!"
'No!' * 0 # => ""

Связанный раздел: см. Преобразование в новую строку.

self + other_string → new_string Показать исходный код
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_enc_new(rb_cString, 0, len1+len2, enc);
    ptr3 = RSTRING_PTR(str3);
    memcpy(ptr3, ptr1, len1);
    memcpy(ptr3+len1, ptr2, len2);
    TERM_FILL(&ptr3[len1+len2], termlen);

    ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
                           ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
    RB_GC_GUARD(str1);
    RB_GC_GUARD(str2);
    return str3;
}

Возвращает новую строку, содержащую other_string, объединённую с self:

'Hello from ' + self.to_s # => "Hello from main"

Связанный раздел: см. Преобразование в новую строку.

+string → new_string or self Показать исходный код
static VALUE
str_uplus(VALUE str)
{
    if (OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
        return rb_str_dup(str);
    }
    else {
        return str;
    }
}

Возвращает self, если self не заморожена и может быть изменена без выдачи предупреждения.

В противном случае возвращает self.dup, которая не заморожена.

Связанный раздел: см. Замораживание и размораживание.

-self → frozen_string Показать исходный код
static VALUE
str_uminus(VALUE str)
{
    if (!BARE_STRING_P(str) && !rb_obj_frozen_p(str)) {
        str = rb_str_dup(str);
    }
    return rb_fstring(str);
}

Возвращает замороженную строку, равную self.

Возвращённая строка является self тогда и только тогда, когда выполняются все следующие условия:

  • self уже заморожена.

  • self является экземпляром String (а не экземпляром подкласса String)

  • У self не заданы переменные экземпляра.

В противном случае возвращённая строка является замороженной копией self.

Возврат self, когда это возможно, позволяет избежать дублирования self; см. дедупликацию данных.

Это также может помочь избежать дублирования других уже существующих строк:

s0 = 'foo'
s1 = 'foo'
s0.object_id == s1.object_id       # => false
(-s0).object_id == (-s1).object_id # => true

Обратите внимание, что метод -@ удобно использовать для определения константы:

FileName = -'config/database.yml'

А его псевдоним dedup лучше подходит для цепочек вызовов:

'foo'.dedup.gsub!('o')

Связанный раздел: см. Замораживание и размораживание.

Также имеет псевдоним: dedup
self << object → self Показать исходный код
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_ascii8bit_appendable_encoding_index(enc, code);

    if (encidx >= 0) {
        rb_str_buf_cat_byte(str1, (unsigned char)code);
    }
    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;
        }
        else if (cr == ENC_CODERANGE_BROKEN) {
            cr = ENC_CODERANGE_UNKNOWN;
        }
        ENC_CODERANGE_SET(str1, cr);
    }
    return str1;
}

Добавляет строковое представление object к self; возвращает self.

Если object — строка, добавляет её к self:

s = 'foo'
s << 'bar' # => "foobar"
s          # => "foobar"

Если object — целое число, его значение считается кодовой точкой; преобразует значение в символ перед конкатенацией:

s = 'foo'
s << 33 # => "foo!"

Кроме того, если кодовая точка находится в диапазоне 0..0xff, а кодировка self — Encoding::US_ASCII, кодировка меняется на Encoding::ASCII_8BIT:

s = 'foo'.encode(Encoding::US_ASCII)
s.encoding # => #<Encoding:US-ASCII>
s << 0xff  # => "foo\xFF"
s.encoding # => #<Encoding:BINARY (ASCII-8BIT)>

Вызывает исключение RangeError, если эта кодовая точка не представима в кодировке self:

s = 'foo'
s.encoding              # => <Encoding:UTF-8>
s << 0x00110000         # 1114112 out of char range (RangeError)
s = 'foo'.encode(Encoding::EUC_JP)
s << 0x00800080         # invalid codepoint 0x800080 in EUC-JP (RangeError)

Связанный раздел: см. Изменение.

self <=> other → -1, 0, 1, or nil Показать исходный код
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);
}

Сравнивает self и other, оценивая их содержимое, а не длину.

Возвращает:

  • -1, если self меньше.

  • 0, если они равны.

  • 1, если self больше.

  • nil, если их невозможно сравнить.

Примеры:

'a'  <=> 'b'  # => -1
'a'  <=> 'ab' # => -1
'a'  <=> 'a'  # => 0
'b'  <=> 'a'  # => 1
'ab' <=> 'a'  # => 1
'a'  <=> :a   # => nil

Класс String включает модуль Comparable; каждый его метод использует String#<=> для сравнения.

Связанный раздел: см. Сравнение.

self == object → true or false Показать исходный код
VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
    if (str1 == str2) return Qtrue;
    if (!RB_TYPE_P(str2, T_STRING)) {
        if (!rb_respond_to(str2, idTo_str)) {
            return Qfalse;
        }
        return rb_equal(str2, str1);
    }
    return rb_str_eql_internal(str1, str2);
}

Возвращает признак того, равно ли object значению self.

Если object — строка, возвращает признак того, что object имеет ту же длину и содержимое, что и self:

s = 'foo'
s == 'foo'  # => true
s == 'food' # => false
s == 'FOO'  # => false

Возвращает false, если кодировки двух строк несовместимы:

"\u{e4 f6 fc}".encode(Encoding::ISO_8859_1) == ("\u{c4 d6 dc}") # => false

Если object не является строкой:

  • Если object поддерживает метод to_str, вызывается object == self и возвращается его значение.

  • Если object не поддерживает to_str, возвращается false.

Связанный раздел: Сравнение.

Также имеет псевдоним: ===
===
Псевдоним для: ==
self =~ object → integer or nil Показать исходный код
static VALUE
rb_str_match(VALUE x, VALUE y)
{
    switch (OBJ_BUILTIN_TYPE(y)) {
      case T_STRING:
        rb_raise(rb_eTypeError, "type mismatch: String given");

      case T_REGEXP:
        return rb_reg_match(y, x);

      default:
        return rb_funcall(y, idEqTilde, 1, x);
    }
}

Если object является Regexp, возвращает индекс первой подстроки в self, соответствующей object, или nil, если совпадение не найдено; обновляет глобальные переменные, связанные с Regexp:

'foo' =~ /f/ # => 0
$~           # => #<MatchData "f">
'foo' =~ /o/ # => 1
$~           # => #<MatchData "o">
'foo' =~ /x/ # => nil
$~           # => nil

Обратите внимание, что string =~ regexp отличается от regexp =~ string (см. Regexp#=~):

number = nil
'no. 9' =~ /(?<number>\d+)/ # => 4
number                      # => nil # Not assigned.
/(?<number>\d+)/ =~ 'no. 9' # => 4
number                      # => "9" # Assigned.

Если object не является Regexp, возвращает значение, возвращённое object =~ self.

Связанный раздел: см. Запросы.

self[index] → new_string or nil Показать исходный код
self[start, length] → new_string or nil
self[range] → new_string or nil
self[regexp, capture = 0] → new_string or nil
self[substring] → new_string or 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 {
            return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
        }
    }
    rb_check_arity(argc, 1, 2);
    return rb_str_aref(str, argv[0]);
}

Возвращает подстроку self, заданную аргументами.

Форма self[index]

Если задан неотрицательный целочисленный аргумент index, возвращает односимвольную подстроку self с индексом символа, равным index:

'hello'[0]    # => "h"
'hello'[4]    # => "o"
'hello'[5]    # => nil
'Привет'[2]   # => "и"
'こんにちは'[4] # => "は"

Если задан отрицательный целочисленный аргумент index, отсчёт ведётся с конца self:

'hello'[-1] # => "o"
'hello'[-5] # => "h"
'hello'[-6] # => nil

Форма self[start, length]

Если заданы целочисленные аргументы start и length, возвращает подстроку размером length символов (если они доступны), начиная с позиции символа, заданной start.

Если аргумент start неотрицательный, смещение равно start:

'hello'[0, 1]  # => "h"
'hello'[0, 5]  # => "hello"
'hello'[0, 6]  # => "hello"
'hello'[2, 3]  # => "llo"
'hello'[2, 0]  # => ""
'hello'[2, -1] # => nil

Если аргумент start отрицательный, отсчёт ведётся с конца self:

'hello'[-1, 1] # => "o"
'hello'[-5, 5] # => "hello"
'hello'[-1, 0] # => ""
'hello'[-6, 5] # => nil

Особый случай: если start равно длине self, возвращает новую пустую строку:

'hello'[5, 3]  # => ""

Форма self[range]

Если задан аргумент Range range, формирует подстроку self[range.start, range.size]:

'hello'[0..2]  # => "hel"
'hello'[0, 3]  # => "hel"

'hello'[0...2] # => "he"
'hello'[0, 2]  # => "he"

'hello'[0, 0]  # => ""
'hello'[0...0] # => ""

Форма self[regexp, capture = 0]

Если задан аргумент Regexp regexp и capture равен нулю, выполняет поиск соответствующей подстроки в self; обновляет глобальные переменные, связанные с Regexp:

'hello'[/ell/]     # => "ell"
'hello'[/l+/]      # => "ll"
'hello'[//]        # => ""
'hello'[/nosuch/]  # => nil

Если capture — положительное целое число n, возвращает группу совпадения номер +n+:

'hello'[/(h)(e)(l+)(o)/]    # => "hello"
'hello'[/(h)(e)(l+)(o)/, 1] # => "h"
$1                          # => "h"
'hello'[/(h)(e)(l+)(o)/, 2] # => "e"
$2                          # => "e"
'hello'[/(h)(e)(l+)(o)/, 3] # => "ll"
'hello'[/(h)(e)(l+)(o)/, 4] # => "o"
'hello'[/(h)(e)(l+)(o)/, 5] # => nil

Форма self[substring]

Если задан строковый аргумент substring, возвращает соответствующую подстроку self, если она найдена:

'hello'['ell']      # => "ell"
'hello'['']         # => ""
'hello'['nosuch']   # => nil
'Привет'['ив']      # => "ив"
'こんにちは'['んにち'] # => "んにち"

Связанный раздел: см. Преобразование в новую строку.

Также имеет псевдоним: slice
self[index] = other_string → new_string Показать исходный код
self[start, length] = other_string → new_string
self[range] = other_string → new_string
self[regexp, capture = 0] = other_string → new_string
self[substring] = other_string → new_string
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_update(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]);
}

Возвращает self, заменив всё его содержимое, подстроку или ничего; возвращает аргумент other_string.

Форма self[index] = other_string

Если задан неотрицательный целочисленный аргумент index, выполняется поиск односимвольной подстроки в self со смещением index:

s = 'hello'
s[0] = 'foo' # => "foo"
s            # => "fooello"

s = 'hello'
s[4] = 'foo' # => "foo"
s            # => "hellfoo"

s = 'hello'
s[5] = 'foo' # => "foo"
s            # => "hellofoo"

s = 'hello'
s[6] = 'foo' # Raises IndexError: index 6 out of string.

Если задан отрицательный целочисленный аргумент index, отсчёт ведётся от конца self:

s = 'hello'
s[-1] = 'foo'  # => "foo"
s              # => "hellfoo"

s = 'hello'
s[-5] = 'foo'  # => "foo"
s              # => "fooello"

s = 'hello'
s[-6] = 'foo'  # Raises IndexError: index -6 out of string.

Форма self[start, length] = other_string

Если заданы целочисленные аргументы start и length, выполняется поиск подстроки размером length символов (если доступно), начиная со смещения, заданного аргументом start.

Если аргумент start неотрицательный, смещение равно start:

s = 'hello'
s[0, 1] = 'foo'  # => "foo"
s                # => "fooello"

s = 'hello'
s[0, 5] = 'foo'  # => "foo"
s                # => "foo"

s = 'hello'
s[0, 9] = 'foo'  # => "foo"
s                # => "foo"

s = 'hello'
s[2, 0] = 'foo'  # => "foo"
s                # => "hefoollo"

s = 'hello'
s[2, -1] = 'foo' # Raises IndexError: negative length -1.

Если аргумент start отрицательный, отсчёт ведётся от конца self:

s = 'hello'
s[-1, 1] = 'foo' # => "foo"
s                # => "hellfoo"

s = 'hello'
s[-1, 9] = 'foo' # => "foo"
s                # => "hellfoo"

s = 'hello'
s[-5, 2] = 'foo' # => "foo"
s                # => "foollo"

s = 'hello'
s[-3, 0] = 'foo' # => "foo"
s                # => "hefoollo"

s = 'hello'
s[-6, 2] = 'foo' # Raises IndexError: index -6 out of string.

Особый случай: если start равно длине self, аргумент добавляется в конец self:

s = 'hello'
s[5, 3] = 'foo' # => "foo"
s               # => "hellofoo"

Форма self[range] = other_string

Если задан аргумент Range range, эквивалентно self[range.start, range.size] = other_string:

s0 = 'hello'
s1 = 'hello'
s0[0..2] = 'foo' # => "foo"
s1[0, 3] = 'foo' # => "foo"
s0               # => "foolo"
s1               # => "foolo"

s = 'hello'
s[0...2] = 'foo' # => "foo"
s                # => "foollo"

s = 'hello'
s[0...0] = 'foo' # => "foo"
s                # => "foohello"

s = 'hello'
s[9..10] = 'foo' # Raises RangeError: 9..10 out of range

Форма self[regexp, capture = 0] = other_string

Если задан аргумент Regexp regexp и capture равно нулю, выполняется поиск соответствующей подстроки в self; обновляются глобальные переменные, связанные с Regexp:

s = 'hello'
s[/l/] = 'L'       # => "L"
[$`, $&, $']       # => ["he", "l", "lo"]
s[/eLlo/] = 'owdy' # => "owdy"
[$`, $&, $']       # => ["h", "eLlo", ""]
s[/eLlo/] = 'owdy' # Raises IndexError: regexp not matched.
[$`, $&, $']       # => [nil, nil, nil]

Если capture — положительное целое число n, выполняется поиск n-й совпавшей группы:

s = 'hello'
s[/(h)(e)(l+)(o)/] = 'foo'    # => "foo"
[$`, $&, $']                  # => ["", "hello", ""]

s = 'hello'
s[/(h)(e)(l+)(o)/, 1] = 'foo' # => "foo"
s                             # => "fooello"
[$`, $&, $']                  # => ["", "hello", ""]

s = 'hello'
s[/(h)(e)(l+)(o)/, 2] = 'foo' # => "foo"
s                             # => "hfoollo"
[$`, $&, $']                  # => ["", "hello", ""]

s = 'hello'
s[/(h)(e)(l+)(o)/, 4] = 'foo' # => "foo"
s                             # => "hellfoo"
[$`, $&, $']                  # => ["", "hello", ""]

s = 'hello'
# => "hello"
s[/(h)(e)(l+)(o)/, 5] = 'foo  # Raises IndexError: index 5 out of regexp.

s = 'hello'
s[/nosuch/] = 'foo'           # Raises IndexError: regexp not matched.

Форма self[substring] = other_string

Если задан строковый аргумент substring:

s = 'hello'
s['l'] = 'foo'  # => "foo"
s  # => "hefoolo"

s = 'hello'
s['ll'] = 'foo'  # => "foo"
s  # => "hefooo"

s = 'Привет'
s['ив'] = 'foo'  # => "foo"
s  # => "Прfooет"

s = 'こんにちは'
s['んにち'] = 'foo'  # => "foo"
s  # => "こfooは"

s['nosuch'] = 'foo' # Raises IndexError: string not matched.

Связанные разделы: см. Изменение.

append_as_bytes(*objects) → self Показать исходный код
VALUE
rb_str_append_as_bytes(int argc, VALUE *argv, VALUE str)
{
    long needed_capacity = 0;
    volatile VALUE t0;
    enum ruby_value_type *types = ALLOCV_N(enum ruby_value_type, t0, argc);

    for (int index = 0; index < argc; index++) {
        VALUE obj = argv[index];
        enum ruby_value_type type = types[index] = rb_type(obj);
        switch (type) {
          case T_FIXNUM:
          case T_BIGNUM:
            needed_capacity++;
            break;
          case T_STRING:
            needed_capacity += RSTRING_LEN(obj);
            break;
          default:
            rb_raise(
                rb_eTypeError,
                "wrong argument type %"PRIsVALUE" (expected String or Integer)",
                rb_obj_class(obj)
            );
            break;
        }
    }

    str_ensure_available_capa(str, needed_capacity);
    char *sptr = RSTRING_END(str);

    for (int index = 0; index < argc; index++) {
        VALUE obj = argv[index];
        enum ruby_value_type type = types[index];
        switch (type) {
          case T_FIXNUM:
          case T_BIGNUM: {
            argv[index] = obj = rb_int_and(obj, INT2FIX(0xff));
            char byte = (char)(NUM2INT(obj) & 0xFF);
            *sptr = byte;
            sptr++;
            break;
          }
          case T_STRING: {
            const char *ptr;
            long len;
            RSTRING_GETMEM(obj, ptr, len);
            memcpy(sptr, ptr, len);
            sptr += len;
            break;
          }
          default:
            rb_bug("append_as_bytes arguments should have been validated");
        }
    }

    STR_SET_LEN(str, RSTRING_LEN(str) + needed_capacity);
    TERM_FILL(sptr, TERM_LEN(str)); /* sentinel */

    int cr = ENC_CODERANGE(str);
    switch (cr) {
      case ENC_CODERANGE_7BIT: {
        for (int index = 0; index < argc; index++) {
            VALUE obj = argv[index];
            enum ruby_value_type type = types[index];
            switch (type) {
              case T_FIXNUM:
              case T_BIGNUM: {
                if (!ISASCII(NUM2INT(obj))) {
                    goto clear_cr;
                }
                break;
              }
              case T_STRING: {
                if (ENC_CODERANGE(obj) != ENC_CODERANGE_7BIT) {
                    goto clear_cr;
                }
                break;
              }
              default:
                rb_bug("append_as_bytes arguments should have been validated");
            }
        }
        break;
      }
      case ENC_CODERANGE_VALID:
        if (ENCODING_GET_INLINED(str) == ENCINDEX_ASCII_8BIT) {
            goto keep_cr;
        }
        else {
            goto clear_cr;
        }
        break;
      default:
        goto clear_cr;
        break;
    }

    RB_GC_GUARD(t0);

  clear_cr:
    // If no fast path was hit, we clear the coderange.
    // append_as_bytes is predominantly meant to be used in
    // buffering situation, hence it's likely the coderange
    // will never be scanned, so it's not worth spending time
    // precomputing the coderange except for simple and common
    // situations.
    ENC_CODERANGE_CLEAR(str);
  keep_cr:
    return str;
}

Объединяет каждый объект из objects с self; возвращает self; не выполняет проверку или преобразование кодировки:

s = 'foo'
s.append_as_bytes(" \xE2\x82") # => "foo \xE2\x82"
s.valid_encoding?              # => false
s.append_as_bytes("\xAC 12")
s.valid_encoding?              # => true

Если заданный объект — целое число, его значение рассматривается как 8-битный байт; если целое число занимает больше одного байта (то есть больше 255), добавляется только младший байт (аналогично String#setbyte):

s = ""
s.append_as_bytes(0, 257) # => "\u0000\u0001"
s.bytesize                # => 2

Связанные разделы: см. Изменение.

ascii_only? → true or false Показать исходный код
static VALUE
rb_str_is_ascii_only_p(VALUE str)
{
    int cr = rb_enc_str_coderange(str);

    return RBOOL(cr == ENC_CODERANGE_7BIT);
}

Возвращает, содержит ли self только символы ASCII:

'abc'.ascii_only?         # => true
"abc\u{6666}".ascii_only? # => false

Связанные разделы: см. Запросы.

b → new_string Показать исходный код
static VALUE
rb_str_b(VALUE str)
{
    VALUE str2;
    if (STR_EMBED_P(str)) {
        str2 = str_alloc_embed(rb_cString, RSTRING_LEN(str) + TERM_LEN(str));
    }
    else {
        str2 = str_alloc_heap(rb_cString);
    }
    str_replace_shared_without_enc(str2, str);

    if (rb_enc_asciicompat(STR_ENC_GET(str))) {
        // BINARY strings can never be broken; they're either 7-bit ASCII or VALID.
        // If we know the receiver's code range then we know the result's code range.
        int cr = ENC_CODERANGE(str);
        switch (cr) {
          case ENC_CODERANGE_7BIT:
            ENC_CODERANGE_SET(str2, ENC_CODERANGE_7BIT);
            break;
          case ENC_CODERANGE_BROKEN:
          case ENC_CODERANGE_VALID:
            ENC_CODERANGE_SET(str2, ENC_CODERANGE_VALID);
            break;
          default:
            ENC_CODERANGE_CLEAR(str2);
            break;
        }
    }

    return str2;
}

Возвращает копию self с кодировкой ASCII-8BIT; исходные байты не изменяются:

s = "\x99"
s.encoding   # => #<Encoding:UTF-8>
t = s.b      # => "\x99"
t.encoding   # => #<Encoding:ASCII-8BIT>

s = "\u4095" # => "䂕"
s.encoding   # => #<Encoding:UTF-8>
s.bytes      # => [228, 130, 149]
t = s.b      # => "\xE4\x82\x95"
t.encoding   # => #<Encoding:ASCII-8BIT>
t.bytes      # => [228, 130, 149]

Связанные разделы: см. Преобразование в новую строку.

byteindex(object, offset = 0) → integer or nil Показать исходный код
static VALUE
rb_str_byteindex_m(int argc, VALUE *argv, VALUE str)
{
    VALUE sub;
    VALUE initpos;
    long pos;

    if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
        long slen = RSTRING_LEN(str);
        pos = NUM2LONG(initpos);
        if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
            if (RB_TYPE_P(sub, T_REGEXP)) {
                rb_backref_set(Qnil);
            }
            return Qnil;
        }
    }
    else {
        pos = 0;
    }

    str_ensure_byte_pos(str, pos);

    if (RB_TYPE_P(sub, T_REGEXP)) {
        if (rb_reg_search(sub, str, pos, 0) >= 0) {
            VALUE match = rb_backref_get();
            struct re_registers *regs = RMATCH_REGS(match);
            pos = BEG(0);
            return LONG2NUM(pos);
        }
    }
    else {
        StringValue(sub);
        pos = rb_str_byteindex(str, sub, pos);
        if (pos >= 0) return LONG2NUM(pos);
    }
    return Qnil;
}

Возвращает целочисленный индекс подстроки в self, отсчитываемый от нуля и задаваемый аргументами object (строкой или Regexp) и offset, либо nil, если такой подстроки нет; возвращаемый индекс — это количество байтов (не символов).

Если object — строка, возвращается индекс первой найденной подстроки, равной object:

s = 'foo'          # => "foo"
s.size             # => 3 # Three 1-byte characters.
s.bytesize         # => 3 # Three bytes.
s.byteindex('f')   # => 0
s.byteindex('o')   # => 1
s.byteindex('oo')  # => 1
s.byteindex('ooo') # => nil

Если object — Regexp, возвращается индекс первой найденной подстроки, соответствующей object; обновляются глобальные переменные, связанные с Regexp:

s = 'foo'
s.byteindex(/f/)   # => 0
$~                 # => #<MatchData "f">
s.byteindex(/o/)   # => 1
s.byteindex(/oo/)  # => 1
s.byteindex(/ooo/) # => nil
$~                 # => nil

Целочисленный аргумент offset, если задан, определяет индекс байта (отсчитываемый от нуля), с которого начинается поиск.

Если offset неотрицательный, поиск начинается с позиции байта offset:

s = 'foo'
s.byteindex('o', 1) # => 1
s.byteindex('o', 2) # => 2
s.byteindex('o', 3) # => nil

Если offset отрицательный, отсчёт ведётся от конца self:

s = 'foo'
s.byteindex('o', -1) # => 2
s.byteindex('o', -2) # => 1
s.byteindex('o', -3) # => 1
s.byteindex('o', -4) # => nil

Вызывает IndexError, если байт в позиции offset не является первым байтом символа:

s = "\uFFFF\uFFFF"       # => "\uFFFF\uFFFF"
s.size                   # => 2 # Two 3-byte characters.
s.bytesize               # => 6 # Six bytes.
s.byteindex("\uFFFF")    # => 0
s.byteindex("\uFFFF", 1) # Raises IndexError
s.byteindex("\uFFFF", 2) # Raises IndexError
s.byteindex("\uFFFF", 3) # => 3
s.byteindex("\uFFFF", 4) # Raises IndexError
s.byteindex("\uFFFF", 5) # Raises IndexError
s.byteindex("\uFFFF", 6) # => nil

Связанные разделы: см. Запросы.

byterindex(object, offset = self.bytesize) → integer or nil Показать исходный код
static VALUE
rb_str_byterindex_m(int argc, VALUE *argv, VALUE str)
{
    VALUE sub;
    VALUE initpos;
    long pos, len = RSTRING_LEN(str);

    if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
        pos = NUM2LONG(initpos);
        if (pos < 0 && (pos += len) < 0) {
            if (RB_TYPE_P(sub, T_REGEXP)) {
                rb_backref_set(Qnil);
            }
            return Qnil;
        }
        if (pos > len) pos = len;
    }
    else {
        pos = len;
    }

    str_ensure_byte_pos(str, pos);

    if (RB_TYPE_P(sub, T_REGEXP)) {
        if (rb_reg_search(sub, str, pos, 1) >= 0) {
            VALUE match = rb_backref_get();
            struct re_registers *regs = RMATCH_REGS(match);
            pos = BEG(0);
            return LONG2NUM(pos);
        }
    }
    else {
        StringValue(sub);
        pos = rb_str_byterindex(str, sub, pos);
        if (pos >= 0) return LONG2NUM(pos);
    }
    return Qnil;
}

Возвращает целочисленный индекс подстроки в self, которая является последним совпадением для заданных object (строки или Regexp) и offset, либо nil, если такой подстроки нет; возвращаемый индекс — это количество байтов (не символов).

Если object — строка, возвращается индекс последней найденной подстроки, равной object:

s = 'foo'           # => "foo"
s.size              # => 3 # Three 1-byte characters.
s.bytesize          # => 3 # Three bytes.
s.byterindex('f')   # => 0
s.byterindex('o')   # => 2
s.byterindex('oo')  # => 1
s.byterindex('ooo') # => nil

Если object — Regexp, возвращается индекс последней найденной подстроки, соответствующей object; обновляются глобальные переменные, связанные с Regexp:

s = 'foo'
s.byterindex(/f/)   # => 0
$~                  # => #<MatchData "f">
s.byterindex(/o/)   # => 2
s.byterindex(/oo/)  # => 1
s.byterindex(/ooo/) # => nil
$~                  # => nil

Последнее совпадение означает совпадение, начинающееся в самой поздней возможной позиции, а не последнее среди самых длинных совпадений:

s = 'foo'
s.byterindex(/o+/) # => 2
$~                 #=> #<MatchData "o">

Чтобы получить последнее самое длинное совпадение, используйте отрицательный просмотр назад:

s = 'foo'
s.byterindex(/(?<!o)o+/) # => 1
$~                       # => #<MatchData "oo">

Или используйте метод byteindex с отрицательным просмотром вперёд:

s = 'foo'
s.byteindex(/o+(?!.*o)/) # => 1
$~                       #=> #<MatchData "oo">

Целочисленный аргумент offset, если задан, определяет индекс байта (отсчитываемый от нуля), на котором заканчивается поиск.

Если offset неотрицательный, поиск заканчивается на позиции байта offset:

s = 'foo'
s.byterindex('o', 0) # => nil
s.byterindex('o', 1) # => 1
s.byterindex('o', 2) # => 2
s.byterindex('o', 3) # => 2

Если offset отрицательный, отсчёт ведётся от конца self:

s = 'foo'
s.byterindex('o', -1) # => 2
s.byterindex('o', -2) # => 1
s.byterindex('o', -3) # => nil

Вызывает IndexError, если байт в позиции offset не является первым байтом символа:

s = "\uFFFF\uFFFF"        # => "\uFFFF\uFFFF"
s.size                    # => 2 # Two 3-byte characters.
s.bytesize                # => 6 # Six bytes.
s.byterindex("\uFFFF")    # => 3
s.byterindex("\uFFFF", 1) # Raises IndexError
s.byterindex("\uFFFF", 2) # Raises IndexError
s.byterindex("\uFFFF", 3) # => 3
s.byterindex("\uFFFF", 4) # Raises IndexError
s.byterindex("\uFFFF", 5) # Raises IndexError
s.byterindex("\uFFFF", 6) # => nil

Связанные разделы: см. Запросы.

bytes → array_of_bytes Показать исходный код
static VALUE
rb_str_bytes(VALUE str)
{
    VALUE ary = WANTARRAY("bytes", RSTRING_LEN(str));
    return rb_str_enumerate_bytes(str, ary);
}

Возвращает массив байтов в self:

'hello'.bytes  # => [104, 101, 108, 108, 111]
'Привет'.bytes # => [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
'こんにちは'.bytes
# => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]

Связанные разделы: см. Преобразование в нестроковое значение.

bytesize → integer Показать исходный код
VALUE
rb_str_bytesize(VALUE str)
{
    return LONG2NUM(RSTRING_LEN(str));
}

Возвращает количество байтов в self.

Обратите внимание, что количество байтов может отличаться от количества символов (возвращаемого методом size):

s = 'foo'
s.bytesize # => 3
s.size     # => 3
s = 'Привет'
s.bytesize # => 12
s.size     # => 6
s = 'こんにちは'
s.bytesize # => 15
s.size     # => 5

Связанные разделы: см. Запросы.

byteslice(offset, length = 1) → string or nil Показать исходный код
byteslice(range) → string or nil
static VALUE
rb_str_byteslice(int argc, VALUE *argv, VALUE str)
{
    if (argc == 2) {
        long beg = NUM2LONG(argv[0]);
        long len = NUM2LONG(argv[1]);
        return str_byte_substr(str, beg, len, TRUE);
    }
    rb_check_arity(argc, 1, 2);
    return str_byte_aref(str, argv[0]);
}

Возвращает подстроку из self или nil, если подстроку невозможно создать.

Если заданы целочисленные аргументы offset и length, возвращается подстрока, начинающаяся с заданного offset и имеющая заданную length (если доступно):

s = '0123456789'   # => "0123456789"
s.byteslice(2)     # => "2"
s.byteslice(200)   # => nil
s.byteslice(4, 3)  # => "456"
s.byteslice(4, 30) # => "456789"

Возвращает nil, если length отрицательный или offset выходит за пределы self:

s.byteslice(4, -1) # => nil
s.byteslice(40, 2) # => nil

Если offset отрицательный, отсчёт ведётся от конца self:

s = '0123456789'   # => "0123456789"
s.byteslice(-4)    # => "6"
s.byteslice(-4, 3) # => "678"

Если задан аргумент Range range, возвращается byteslice(range.begin, range.size):

s = '0123456789'    # => "0123456789"
s.byteslice(4..6)   # => "456"
s.byteslice(-6..-4) # => "456"
s.byteslice(5..2)   # => "" # range.size is zero.
s.byteslice(40..42) # => nil

Начальное и конечное смещения не обязаны совпадать с границами символов:

s = 'こんにちは'
s.byteslice(0, 3) # => "こ"
s.byteslice(1, 3) # => "\x81\x93\xE3"

Кодировки self и возвращаемой подстроки всегда совпадают:

s.encoding                 # => #<Encoding:UTF-8>
s.byteslice(0, 3).encoding # => #<Encoding:UTF-8>
s.byteslice(1, 3).encoding # => #<Encoding:UTF-8>

Однако в зависимости от границ символов кодировка возвращаемой подстроки может быть недопустимой:

s.valid_encoding?                 # => true
s.byteslice(0, 3).valid_encoding? # => true
s.byteslice(1, 3).valid_encoding? # => false

Связанные разделы: см. Преобразование в новую строку.

bytesplice(offset, length, str) → self Показать исходный код
bytesplice(offset, length, str, str_offset, str_length) → self
bytesplice(range, str) → self
bytesplice(range, str, str_range) → self
static VALUE
rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
{
    long beg, len, vbeg, vlen;
    VALUE val;
    int cr;

    rb_check_arity(argc, 2, 5);
    if (!(argc == 2 || argc == 3 || argc == 5)) {
        rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
    }
    if (argc == 2 || (argc == 3 && !RB_INTEGER_TYPE_P(argv[0]))) {
        if (!rb_range_beg_len(argv[0], &beg, &len, RSTRING_LEN(str), 2)) {
            rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
                     rb_builtin_class_name(argv[0]));
        }
        val = argv[1];
        StringValue(val);
        if (argc == 2) {
            /* bytesplice(range, str) */
            vbeg = 0;
            vlen = RSTRING_LEN(val);
        }
        else {
            /* bytesplice(range, str, str_range) */
            if (!rb_range_beg_len(argv[2], &vbeg, &vlen, RSTRING_LEN(val), 2)) {
                rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
                         rb_builtin_class_name(argv[2]));
            }
        }
    }
    else {
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        val = argv[2];
        StringValue(val);
        if (argc == 3) {
            /* bytesplice(index, length, str) */
            vbeg = 0;
            vlen = RSTRING_LEN(val);
        }
        else {
            /* bytesplice(index, length, str, str_index, str_length) */
            vbeg = NUM2LONG(argv[3]);
            vlen = NUM2LONG(argv[4]);
        }
    }
    str_check_beg_len(str, &beg, &len);
    str_check_beg_len(val, &vbeg, &vlen);
    str_modify_keep_cr(str);

    if (RB_UNLIKELY(ENCODING_GET_INLINED(str) != ENCODING_GET_INLINED(val))) {
        rb_enc_associate(str, rb_enc_check(str, val));
    }

    rb_str_update_1(str, beg, len, val, vbeg, vlen);
    cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
    if (cr != ENC_CODERANGE_BROKEN)
        ENC_CODERANGE_SET(str, cr);
    return str;
}

Заменяет целевые байты в self на исходные байты из заданной строки str; возвращает self.

В первой форме аргументы offset и length задают целевые байты, а исходными байтами служат все байты заданного str:

'0123456789'.bytesplice(0, 3, 'abc')  # => "abc3456789"
'0123456789'.bytesplice(3, 3, 'abc')  # => "012abc6789"
'0123456789'.bytesplice(0, 50, 'abc') # => "abc"
'0123456789'.bytesplice(50, 3, 'abc') # Raises IndexError.

Количество целевых и исходных байтов может различаться:

'0123456789'.bytesplice(0, 6, 'abc') # => "abc6789"      # Shorter source.
'0123456789'.bytesplice(0, 1, 'abc') # => "abc123456789" # Shorter target.

Любое из этих количеств может быть равно нулю (то есть задавать пустую строку):

'0123456789'.bytesplice(0, 3, '')    # => "3456789"       # Empty source.
'0123456789'.bytesplice(0, 0, 'abc') # => "abc0123456789" # Empty target.

Во второй форме, как и в первой, аргументы offset и length задают целевые байты; аргумент str содержит исходные байты, а дополнительные аргументы str_offset и str_length задают фактические исходные байты:

'0123456789'.bytesplice(0, 3, 'abc', 0, 3) # => "abc3456789"
'0123456789'.bytesplice(0, 3, 'abc', 1, 1) # => "b3456789"      # Shorter source.
'0123456789'.bytesplice(0, 1, 'abc', 0, 3) # => "abc123456789"  # Shorter target.
'0123456789'.bytesplice(0, 3, 'abc', 1, 0) # => "3456789"       # Empty source.
'0123456789'.bytesplice(0, 0, 'abc', 0, 3) # => "abc0123456789" # Empty target.

В третьей форме аргумент range задаёт целевые байты, а исходными байтами служат все байты заданного str:

'0123456789'.bytesplice(0..2, 'abc')  # => "abc3456789"
'0123456789'.bytesplice(3..5, 'abc')  # => "012abc6789"
'0123456789'.bytesplice(0..5, 'abc')  # => "abc6789"       # Shorter source.
'0123456789'.bytesplice(0..0, 'abc')  # => "abc123456789"  # Shorter target.
'0123456789'.bytesplice(0..2, '')     # => "3456789"       # Empty source.
'0123456789'.bytesplice(0...0, 'abc') # => "abc0123456789" # Empty target.

В четвёртой форме, как и в третьей, аргумент range задаёт целевые байты; аргумент str содержит исходные байты, а дополнительный аргумент str_range задаёт фактические исходные байты:

'0123456789'.bytesplice(0..2, 'abc', 0..2)  # => "abc3456789"
'0123456789'.bytesplice(3..5, 'abc', 0..2)  # => "012abc6789"
'0123456789'.bytesplice(0..2, 'abc', 0..1)  # => "ab3456789"     # Shorter source.
'0123456789'.bytesplice(0..1, 'abc', 0..2)  # => "abc23456789"   # Shorter target.
'0123456789'.bytesplice(0..2, 'abc', 0...0) # => "3456789"       # Empty source.
'0123456789'.bytesplice(0...0, 'abc', 0..2) # => "abc0123456789" # Empty target.

Во всех формах начала и концы исходных и целевых байтов должны находиться на границах символов.

В этих примерах self содержит пять 3-байтовых символов, поэтому границы символов находятся по смещениям 0, 3, 6, 9, 12 и 15.

'こんにちは'.bytesplice(0, 3, 'abc') # => "abcんにちは"
'こんにちは'.bytesplice(1, 3, 'abc') # Raises IndexError.
'こんにちは'.bytesplice(0, 2, 'abc') # Raises IndexError.
capitalize(mapping = :ascii) → new_string Показать исходный код
static VALUE
rb_str_capitalize(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
    VALUE ret;

    flags = check_case_options(argc, argv, flags);
    enc = str_true_enc(str);
    if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str;
    if (flags&ONIGENC_CASE_ASCII_ONLY) {
        ret = rb_str_new(0, RSTRING_LEN(str));
        rb_str_ascii_casemap(str, ret, &flags, enc);
    }
    else {
        ret = rb_str_casemap(str, &flags, enc);
    }
    return ret;
}

Возвращает строку, содержащую символы из self, регистр которых может быть изменён:

  • Первый символ переводится в верхний регистр.

  • Все остальные символы переводятся в нижний регистр.

Примеры:

'hello'.capitalize  # => "Hello"
'HELLO'.capitalize  # => "Hello"
'straße'.capitalize # => "Straße"  # Lowercase 'ß' not changed.
'STRAẞE'.capitalize # => "Straße"  # Uppercase 'ẞ' downcased to 'ß'.
'привет'.capitalize # => "Привет"
'ПРИВЕТ'.capitalize # => "Привет"

У некоторых символов (и некоторых наборов символов) нет вариантов в верхнем и нижнем регистре; см. преобразование регистра:

s = '1, 2, 3, ...'
s.capitalize == s # => true
s = 'こんにちは'
s.capitalize == s # => true

Преобразование регистра зависит от заданного mapping, которым может быть :ascii, :fold или :turkic; см. преобразования регистра.

Связанные методы: см. Преобразование в новую строку.

capitalize!(mapping = :ascii) → self or nil Показать исходный код
static VALUE
rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;

    flags = check_case_options(argc, argv, flags);
    str_modify_keep_cr(str);
    enc = str_true_enc(str);
    if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
    if (flags&ONIGENC_CASE_ASCII_ONLY)
        rb_str_ascii_casemap(str, str, &flags, enc);
    else
        str_shared_replace(str, rb_str_casemap(str, &flags, enc));

    if (ONIGENC_CASE_MODIFIED&flags) return str;
    return Qnil;
}

Как String#capitalize, но:

  • Изменяет регистр символов в self (а не в копии self).

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные методы: см. Изменение.

casecmp(other_string) → -1, 0, 1, or 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);
}

Сравнивает self и other_string без учёта регистра; возвращает:

  • -1, если self.downcase меньше other_string.downcase.

  • 0, если они равны.

  • 1, если self.downcase больше other_string.downcase.

  • nil, если их невозможно сравнить.

См. преобразование регистра.

Примеры:

'foo'.casecmp('goo')  # => -1
'goo'.casecmp('foo')  # => 1
'foo'.casecmp('food') # => -1
'food'.casecmp('foo') # => 1
'FOO'.casecmp('foo')  # => 0
'foo'.casecmp('FOO')  # => 0
'foo'.casecmp(1)      # => nil

Связанные методы: см. Сравнение.

casecmp?(other_string) → true, false, or 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, если self и other_string равны после преобразования регистра Unicode, false, если они не равны, и nil, если их невозможно сравнить.

См. преобразование регистра.

Примеры:

'foo'.casecmp?('goo')  # => false
'goo'.casecmp?('foo')  # => false
'foo'.casecmp?('food') # => false
'food'.casecmp?('foo') # => false
'FOO'.casecmp?('foo')  # => true
'foo'.casecmp?('FOO')  # => true
'foo'.casecmp?(1)      # => nil

Связанные методы: см. Сравнение.

center(size, pad_string = ' ') → new_string Показать исходный код
static VALUE
rb_str_center(int argc, VALUE *argv, VALUE str)
{
    return rb_str_justify(argc, argv, str, 'c');
}

Возвращает копию self, выровненную по центру.

Если целочисленный аргумент size больше размера self (в символах), возвращает новую строку длиной size, являющуюся копией self, выровненной по центру и дополненной с одной или обеих сторон строкой pad_string:

'hello'.center(6)             # => "hello "               # Padded on one end.
'hello'.center(10)            # => "  hello   "           # Padded on both ends.
'hello'.center(20, '-|')      # => "-|-|-|-hello-|-|-|-|" # Some padding repeated.
'hello'.center(10, 'abcdefg') # => "abhelloabc"           # Some padding not used.
'  hello  '.center(13)        # => "    hello    "
'Привет'.center(10)           # => "  Привет  "
'こんにちは'.center(10)         # => "  こんにちは   "      # Multi-byte characters.

Если size меньше или равен размеру self, возвращает копию self без дополнения:

'hello'.center(5)   # => "hello"
'hello'.center(-10) # => "hello"

Связанные методы: см. Преобразование в новую строку.

chars → array_of_characters Показать исходный код
static VALUE
rb_str_chars(VALUE str)
{
    VALUE ary = WANTARRAY("chars", rb_str_strlen(str));
    return rb_str_enumerate_chars(str, ary);
}

Возвращает массив символов из self:

'hello'.chars     # => ["h", "e", "l", "l", "o"]
'Привет'.chars    # => ["П", "р", "и", "в", "е", "т"]
'こんにちは'.chars # => ["こ", "ん", "に", "ち", "は"]
''.chars          # => []

Связанные методы: см. Преобразование в объект, не являющийся строкой.

chomp(line_sep = $/) → new_string Показать исходный код
static VALUE
rb_str_chomp(int argc, VALUE *argv, VALUE str)
{
    VALUE rs = chomp_rs(argc, argv);
    if (NIL_P(rs)) return str_duplicate(rb_cString, str);
    return rb_str_subseq(str, 0, chompped_length(str, rs));
}

Возвращает новую строку, скопированную из self, из которой могут быть удалены конечные символы:

Если line_sep равно "\n", удаляет один или два последних символа, если это "\r", "\n" или "\r\n" (но не "\n\r"):

$/                    # => "\n"
"abc\r".chomp         # => "abc"
"abc\n".chomp         # => "abc"
"abc\r\n".chomp       # => "abc"
"abc\n\r".chomp       # => "abc\n"
"тест\r\n".chomp      # => "тест"
"こんにちは\r\n".chomp  # => "こんにちは"

Если line_sep равно '' (пустой строке), удаляет несколько повторяющихся конечных символов "\n" или "\r\n" (но не "\r" или "\n\r"):

"abc\n\n\n".chomp('')           # => "abc"
"abc\r\n\r\n\r\n".chomp('')     # => "abc"
"abc\n\n\r\n\r\n\n\n".chomp('') # => "abc"
"abc\n\r\n\r\n\r".chomp('')     # => "abc\n\r\n\r\n\r"
"abc\r\r\r".chomp('')           # => "abc\r\r\r"

Если line_sep не равно ни "\n", ни '', удаляет один конечный разделитель строки, если он есть:

'abcd'.chomp('cd')   # => "ab"
'abcdcd'.chomp('cd') # => "abcd"
'abcd'.chomp('xx')   # => "abcd"

Связанные методы: см. Преобразование в новую строку.

chomp!(line_sep = $/) → self or nil Показать исходный код
static VALUE
rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
{
    VALUE rs;
    str_modifiable(str);
    if (RSTRING_LEN(str) == 0 && argc < 2) return Qnil;
    rs = chomp_rs(argc, argv);
    if (NIL_P(rs)) return Qnil;
    return rb_str_chomp_string(str, rs);
}

Как String#chomp, но:

  • Удаляет конечные символы из self (а не из копии self).

  • Возвращает self, если какие-либо символы были удалены, и nil в противном случае.

Связанные методы: см. Изменение.

chop → new_string Показать исходный код
static VALUE
rb_str_chop(VALUE str)
{
    return rb_str_subseq(str, 0, chopped_length(str));
}

Возвращает новую строку, скопированную из self, из которой могут быть удалены конечные символы.

Удаляет "\r\n", если это два последних символа.

"abc\r\n".chop      # => "abc"
"тест\r\n".chop     # => "тест"
"こんにちは\r\n".chop # => "こんにちは"

В противном случае удаляет последний символ, если он есть.

'abcd'.chop     # => "abc"
'тест'.chop     # => "тес"
'こんにちは'.chop # => "こんにち"
''.chop         # => ""

Если нужно удалить только разделитель новой строки в конце строки, лучше использовать String#chomp.

Связанные методы: см. Преобразование в новую строку.

chop! → self or nil Показать исходный код
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;
}

Как String#chop, но:

  • Удаляет конечные символы из self (а не из копии self).

  • Возвращает self, если какие-либо символы были удалены, и nil в противном случае.

Связанные методы: см. Изменение.

chr → string Показать исходный код
static VALUE
rb_str_chr(VALUE str)
{
    return rb_str_substr(str, 0, 1);
}

Возвращает строку, содержащую первый символ из self:

'hello'.chr     # => "h"
'тест'.chr      # => "т"
'こんにちは'.chr # => "こ"
''.chr          # => ""

Связанные методы: см. Преобразование в новую строку.

clear → self Показать исходный код
static VALUE
rb_str_clear(VALUE str)
{
    str_discard(str);
    STR_SET_EMBED(str);
    STR_SET_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;
}

Удаляет содержимое self:

s = 'foo'
s.clear # => ""
s       # => ""

Связанные методы: см. Изменение.

codepoints → array_of_integers Показать исходный код
static VALUE
rb_str_codepoints(VALUE str)
{
    VALUE ary = WANTARRAY("codepoints", rb_str_strlen(str));
    return rb_str_enumerate_codepoints(str, ary);
}

Возвращает массив кодовых точек из self; каждая кодовая точка — целочисленное значение символа:

'hello'.codepoints     # => [104, 101, 108, 108, 111]
'тест'.codepoints      # => [1090, 1077, 1089, 1090]
'こんにちは'.codepoints # => [12371, 12435, 12395, 12385, 12399]
''.codepoints          # => []

Связанные методы: см. Преобразование в объект, не являющийся строкой.

concat(*objects) → string Показать исходный код
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;
}

Добавляет каждый объект из objects к self; возвращает self:

'foo'.concat('bar', 'baz') # => "foobarbaz"

Для каждого заданного объекта object, являющегося целым числом, его значение считается кодовой точкой и перед добавлением преобразуется в символ:

'foo'.concat(32, 'bar', 32, 'baz') # => "foo bar baz" # Embeds spaces.
'те'.concat(1089, 1090)            # => "тест"
'こん'.concat(12395, 12385, 12399)  # => "こんにちは"

Связанные методы: см. Преобразование в новую строку.

count(*selectors) → integer Показать исходный код
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;
    size_t n = 0;

    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 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 SIZET2NUM(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);
    while (s < send) {
        unsigned int c;

        if (ascompat && (c = *(unsigned char*)s) < 0x80) {
            if (table[c]) {
                n++;
            }
            s++;
        }
        else {
            int clen;
            c = rb_enc_codepoint_len(s, send, &clen, enc);
            if (tr_find(c, table, del, nodel)) {
                n++;
            }
            s += clen;
        }
    }

    return SIZET2NUM(n);
}

Возвращает общее количество символов в self, соответствующих заданным селекторам.

Для одного односимвольного селектора возвращает количество вхождений этого символа:

s = 'abracadabra'
s.count('a') # => 5
s.count('b') # => 2
s.count('x') # => 0
s.count('')  # => 0

s = 'тест'
s.count('т')  # => 2
s.count('е')  # => 1

s = 'よろしくお願いします'
s.count('よ')  # => 1
s.count('し')  # => 2

Для одного многосимвольного селектора возвращает количество вхождений всех указанных символов:

s = 'abracadabra'
s.count('ab')     # => 7
s.count('abc')    # => 8
s.count('abcd')   # => 9
s.count('abcdr')  # => 11
s.count('abcdrx') # => 11

Порядок и повторения не имеют значения:

s.count('ba')   == s.count('ab') # => true
s.count('baab') == s.count('ab') # => true

Для нескольких селекторов формирует единый селектор, представляющий собой пересечение символов во всех селекторах, и возвращает количество вхождений символов, соответствующих этому селектору:

s = 'abcdefg'
s.count('abcde', 'dcbfg') == s.count('bcd') # => true
s.count('abc', 'def')     == s.count('')    # => true

В селекторе символов три символа обрабатываются особым образом:

  • Карет ('^') служит оператором отрицания для непосредственно следующих за ним символов:

    s = 'abracadabra'
    s.count('^bc') # => 8  # Count of all except 'b' and 'c'.
    
  • Дефис ('-') между двумя другими символами задаёт диапазон символов:

    s = 'abracadabra'
    s.count('a-c') # => 8  # Count of all 'a', 'b', and 'c'.
    
  • Обратная косая черта ('\') экранирует карет, дефис или другую обратную косую черту:

    s = 'abracadabra'
    s.count('\^bc')           # => 3  # Count of '^', 'b', and 'c'.
    s.count('a\-c')           # => 6  # Count of 'a', '-', and 'c'.
    'foo\bar\baz'.count('\\') # => 2  # Count of '\'.
    

Эти варианты использования можно комбинировать:

s = 'abracadabra'
s.count('a-cq-t') # => 10  # Multiple ranges.
s.count('ac-d')   # => 7   # Range mixed with plain characters.
s.count('^a-c')   # => 3   # Range mixed with negation.

Для нескольких селекторов можно использовать все варианты, включая отрицания, диапазоны и экранирование.

s = 'abracadabra'
s.count('^abc', '^def') == s.count('^abcdef') # => true
s.count('a-e', 'c-g')   == s.count('cde')     # => true
s.count('^abc', 'c-g')  == s.count('defg')    # => true

См. также: Запросы.

crypt(salt_str) → new_string Показать исходный код
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
    char *tmp_buf;
    extern char *crypt(const char *, const char *);
#   define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
#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);
    s = StringValueCStr(str);
    saltp = RSTRING_PTR(salt);
    if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
        rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
    }

#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
    rb_nativethread_lock_lock(&crypt_mutex.lock);
    res = crypt(s, saltp);
#endif
    if (!res) {
        int err = errno;
        CRYPT_END();
        rb_syserr_fail(err, "crypt");
    }
#ifdef HAVE_CRYPT_R
    result = rb_str_new_cstr(res);
    CRYPT_END();
#else
    // We need to copy this buffer because it's static and we need to unlock the mutex
    // before allocating a new object (the string to be returned). If we allocate while
    // holding the lock, we could run GC which fires the VM barrier and causes a deadlock
    // if other ractors are waiting on this lock.
    size_t res_size = strlen(res)+1;
    tmp_buf = ALLOCA_N(char, res_size); // should be small enough to alloca
    memcpy(tmp_buf, res, res_size);
    res = tmp_buf;
    CRYPT_END();
    result = rb_str_new_cstr(res);
#endif
    return result;
}

Возвращает строку, полученную вызовом функции стандартной библиотеки crypt(3) с аргументами str и salt_str именно в таком порядке. Пожалуйста, больше не используйте этот метод. Он устарел и предоставляется только для обратной совместимости со скриптами Ruby прошлых лет. Его не следует применять в современных программах по нескольким причинам:

  • Поведение функции C crypt(3) зависит от операционной системы, в которой она выполняется. Сгенерированная строка не переносима между системами.

  • В некоторых операционных системах, например Mac OS, crypt(3) никогда не завершается ошибкой (то есть может незаметно привести к неожиданным результатам).

  • В некоторых операционных системах, например Mac OS, crypt(3) не является потокобезопасным.

  • Так называемый «традиционный» способ использования crypt(3) очень и очень слаб. Согласно man-странице, традиционный вывод crypt(3) в Linux имеет всего 2**56 вариантов; сегодня такой хеш слишком легко подобрать перебором. Кроме того, это поведение используется по умолчанию.

  • Для повышения надёжности в некоторых операционных системах реализован так называемый «модульный» способ использования. Для его применения необходимо вручную сформировать сложный параметр salt_str. Ошибки при создании корректной строки соли обычно не приводят к сообщениям об ошибке; опечатки в параметрах, как правило, невозможно обнаружить.

    • Например, в следующем примере второй вызов String#crypt неверен: в параметре «round=» допущена опечатка (пропущена буква «s»). Однако вызов не завершается ошибкой, а генерирует неожиданный результат.

      "foo".crypt("$5$rounds=1000$salt$") # OK, proper usage
      "foo".crypt("$5$round=1000$salt$")  # Typo not detected
      
  • Даже в «модульном» режиме некоторые хеш-функции считаются устаревшими и больше не рекомендуются к использованию; например, модуль $1$ официально заброшен его автором: см. phk.freebsd.dk/sagas/md5crypt_eol/ . Другой пример: модуль $3$ считается полностью небезопасным: см. man-страницу FreeBSD.

  • В некоторых операционных системах, например Mac OS, модульный режим отсутствует. Однако, как сказано выше, crypt(3) в Mac OS никогда не завершается ошибкой. Это означает, что даже при формировании корректной строки соли всё равно создаётся традиционный хеш DES, и вы никак не сможете об этом узнать.

    "foo".crypt("$5$rounds=1000$salt$") # => "$5fNPQMxC5j6."
    

Если по какой-либо причине вы не можете перейти на другие современные алгоритмы хеширования паролей, установите гем string-crypt и require 'string/crypt', чтобы продолжить его использовать.

-self → frozen_string

Возвращает замороженную строку, равную self.

Возвращённая строка является self тогда и только тогда, когда выполняются все следующие условия:

  • self уже заморожена.

  • self является экземпляром String (а не экземпляром подкласса String)

  • Для self не заданы переменные экземпляра.

В противном случае возвращённая строка является замороженной копией self.

Если возможно, возвращение self позволяет избежать дублирования self; см. дедупликация данных.

Это также может помочь избежать дублирования других уже существующих строк:

s0 = 'foo'
s1 = 'foo'
s0.object_id == s1.object_id       # => false
(-s0).object_id == (-s1).object_id # => true

Обратите внимание, что метод -@ удобен для определения константы:

FileName = -'config/database.yml'

А его псевдоним dedup лучше подходит для цепочек вызовов:

'foo'.dedup.gsub!('o')

См. также: Замораживание/размораживание.

Псевдоним для: -@
delete(*selectors) → new_string Показать исходный код
static VALUE
rb_str_delete(int argc, VALUE *argv, VALUE str)
{
    str = str_duplicate(rb_cString, str);
    rb_str_delete_bang(argc, argv, str);
    return str;
}

Возвращает новую строку, являющуюся копией self, из которой удалены определённые символы; удаляются все вхождения символов, указанных в заданной строке selectors.

Для одного односимвольного селектора удаляются все вхождения этого символа:

s = 'abracadabra'
s.delete('a') # => "brcdbr"
s.delete('b') # => "aracadara"
s.delete('x') # => "abracadabra"
s.delete('')  # => "abracadabra"

s = 'тест'
s.delete('т') # => "ес"
s.delete('е') # => "тст"

s = 'よろしくお願いします'
s.delete('よ') # => "ろしくお願いします"
s.delete('し') # => "よろくお願います"

Для одного многосимвольного селектора удаляются все вхождения указанных символов:

s = 'abracadabra'
s.delete('ab')     # => "rcdr"
s.delete('abc')    # => "rdr"
s.delete('abcd')   # => "rr"
s.delete('abcdr')  # => ""
s.delete('abcdrx') # => ""

Порядок и повторения не имеют значения:

s.delete('ba')   == s.delete('ab') # => true
s.delete('baab') == s.delete('ab') # => true

Для нескольких селекторов формируется единый селектор, представляющий собой пересечение символов во всех селекторах, и удаляются все вхождения символов, указанных этим селектором:

s = 'abcdefg'
s.delete('abcde', 'dcbfg') == s.delete('bcd') # => true
s.delete('abc', 'def')     == s.delete('')    # => true

В селекторе символов три символа обрабатываются особым образом:

  • Карет ('^') служит оператором отрицания для непосредственно следующих за ним символов:

    s = 'abracadabra'
    s.delete('^bc') # => "bcb"  # Deletes all except 'b' and 'c'.
    
  • Дефис ('-') между двумя другими символами задаёт диапазон символов:

    s = 'abracadabra'
    s.delete('a-c') # => "rdr"  # Deletes all 'a', 'b', and 'c'.
    
  • Обратная косая черта ('\') экранирует карет, дефис или другую обратную косую черту:

    s = 'abracadabra'
    s.delete('\^bc')           # => "araadara"   # Deletes all '^', 'b', and 'c'.
    s.delete('a\-c')           # => "brdbr"      # Deletes all 'a', '-', and 'c'.
    'foo\bar\baz'.delete('\\') # => "foobarbaz"  # Deletes all '\'.
    

Эти варианты использования можно комбинировать:

s = 'abracadabra'
s.delete('a-cq-t') # => "d"         # Multiple ranges.
s.delete('ac-d')   # => "brbr"      # Range mixed with plain characters.
s.delete('^a-c')   # => "abacaaba"  # Range mixed with negation.

Для нескольких селекторов можно использовать все варианты, включая отрицания, диапазоны и экранирование.

s = 'abracadabra'
s.delete('^abc', '^def') == s.delete('^abcdef') # => true
s.delete('a-e', 'c-g')   == s.delete('cde')     # => true
s.delete('^abc', 'c-g')  == s.delete('defg')    # => true

См. также: Преобразование в новую строку.

delete!(*selectors) → self or nil Показать исходный код
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;
}

Как String#delete, но изменяет self на месте; возвращает self, если были удалены какие-либо символы, и nil в противном случае.

См. также: Изменение.

delete_prefix(prefix) → new_string Показать исходный код
static VALUE
rb_str_delete_prefix(VALUE str, VALUE prefix)
{
    long prefixlen;

    prefixlen = deleted_prefix_length(str, prefix);
    if (prefixlen <= 0) return str_duplicate(rb_cString, str);

    return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
}

Возвращает копию self с удалённой начальной подстрокой prefix:

'oof'.delete_prefix('o')          # => "of"
'oof'.delete_prefix('oo')         # => "f"
'oof'.delete_prefix('oof')        # => ""
'oof'.delete_prefix('x')          # => "oof"
'тест'.delete_prefix('те')        # => "ст"
'こんにちは'.delete_prefix('こん')  # => "にちは"

См. также: Преобразование в новую строку.

delete_prefix!(prefix) → self or nil Показать исходный код
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);
}

Как String#delete_prefix, но self изменяется на месте; возвращает self, если префикс удалён, и nil в противном случае.

См. также: Изменение.

delete_suffix(suffix) → new_string Показать исходный код
static VALUE
rb_str_delete_suffix(VALUE str, VALUE suffix)
{
    long suffixlen;

    suffixlen = deleted_suffix_length(str, suffix);
    if (suffixlen <= 0) return str_duplicate(rb_cString, str);

    return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
}

Возвращает копию self с удалённой конечной подстрокой suffix:

'foo'.delete_suffix('o')           # => "fo"
'foo'.delete_suffix('oo')          # => "f"
'foo'.delete_suffix('foo')         # => ""
'foo'.delete_suffix('f')           # => "foo"
'foo'.delete_suffix('x')           # => "foo"
'тест'.delete_suffix('ст')         # => "те"
'こんにちは'.delete_suffix('ちは')  # => "こんに"

См. также: Преобразование в новую строку.

delete_suffix!(suffix) → self or nil Показать исходный код
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;
}

Как String#delete_suffix, но self изменяется на месте; возвращает self, если суффикс удалён, и nil в противном случае.

См. также: Изменение.

downcase(mapping = :ascii) → new_string Показать исходный код
static VALUE
rb_str_downcase(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
    VALUE ret;

    flags = check_case_options(argc, argv, flags);
    enc = str_true_enc(str);
    if (case_option_single_p(flags, enc, str)) {
        ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
        str_enc_copy_direct(ret, str);
        downcase_single(ret);
    }
    else if (flags&ONIGENC_CASE_ASCII_ONLY) {
        ret = rb_str_new(0, RSTRING_LEN(str));
        rb_str_ascii_casemap(str, ret, &flags, enc);
    }
    else {
        ret = rb_str_casemap(str, &flags, enc);
    }

    return ret;
}

Возвращает новую строку, содержащую символы self в нижнем регистре:

'HELLO'.downcase        # => "hello"
'STRAẞE'.downcase       # => "straße"
'ПРИВЕТ'.downcase       # => "привет"
'RubyGems.org'.downcase # => "rubygems.org"

Некоторые символы (и некоторые наборы символов) не имеют вариантов в верхнем и нижнем регистре; см. Изменение регистра:

s = '1, 2, 3, ...'
s.downcase == s # => true
s = 'こんにちは'
s.downcase == s # => true

Преобразование регистра зависит от заданного mapping, которым может быть :ascii, :fold или :turkic; см. Преобразования регистра.

См. также: Преобразование в новую строку.

downcase!(mapping) → self or nil Показать исходный код
static VALUE
rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;

    flags = check_case_options(argc, argv, flags);
    str_modify_keep_cr(str);
    enc = str_true_enc(str);
    if (case_option_single_p(flags, enc, str)) {
        if (downcase_single(str))
            flags |= ONIGENC_CASE_MODIFIED;
    }
    else if (flags&ONIGENC_CASE_ASCII_ONLY)
        rb_str_ascii_casemap(str, str, &flags, enc);
    else
        str_shared_replace(str, rb_str_casemap(str, &flags, enc));

    if (ONIGENC_CASE_MODIFIED&flags) return str;
    return Qnil;
}

Как String#downcase, но:

  • Изменяет регистр символов в self (а не в копии self).

  • Возвращает self, если были внесены изменения, и nil в противном случае.

См. также: Изменение.

dump → new_string Показать исходный код
VALUE
rb_str_dump(VALUE str)
{
    int encidx = rb_enc_get_index(str);
    rb_encoding *enc = rb_enc_from_index(encidx);
    long len;
    const char *p, *pend;
    char *q, *qend;
    VALUE result;
    int u8 = (encidx == rb_utf8_encindex());
    static const char nonascii_suffix[] = ".dup.force_encoding(\"%s\")";

    len = 2;                    /* "" */
    if (!rb_enc_asciicompat(enc)) {
        len += strlen(nonascii_suffix) - rb_strlen_lit("%s");
        len += strlen(enc->name);
    }

    p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
    while (p < pend) {
        int clen;
        unsigned char c = *p++;

        switch (c) {
          case '"':  case '\\':
          case '\n': case '\r':
          case '\t': case '\f':
          case '\013': case '\010': case '\007': case '\033':
            clen = 2;
            break;

          case '#':
            clen = IS_EVSTR(p, pend) ? 2 : 1;
            break;

          default:
            if (ISPRINT(c)) {
                clen = 1;
            }
            else {
                if (u8 && c > 0x7F) {   /* \u notation */
                    int n = rb_enc_precise_mbclen(p-1, pend, enc);
                    if (MBCLEN_CHARFOUND_P(n)) {
                        unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
                        if (cc <= 0xFFFF)
                            clen = 6;  /* \uXXXX */
                        else if (cc <= 0xFFFFF)
                            clen = 9;  /* \u{XXXXX} */
                        else
                            clen = 10; /* \u{XXXXXX} */
                        p += MBCLEN_CHARFOUND_LEN(n)-1;
                        break;
                    }
                }
                clen = 4;       /* \xNN */
            }
            break;
        }

        if (clen > LONG_MAX - len) {
            rb_raise(rb_eRuntimeError, "string size too big");
        }
        len += clen;
    }

    result = rb_str_new(0, len);
    p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
    q = RSTRING_PTR(result); qend = q + len + 1;

    *q++ = '"';
    while (p < pend) {
        unsigned char c = *p++;

        if (c == '"' || c == '\\') {
            *q++ = '\\';
            *q++ = c;
        }
        else if (c == '#') {
            if (IS_EVSTR(p, pend)) *q++ = '\\';
            *q++ = '#';
        }
        else if (c == '\n') {
            *q++ = '\\';
            *q++ = 'n';
        }
        else if (c == '\r') {
            *q++ = '\\';
            *q++ = 'r';
        }
        else if (c == '\t') {
            *q++ = '\\';
            *q++ = 't';
        }
        else if (c == '\f') {
            *q++ = '\\';
            *q++ = 'f';
        }
        else if (c == '\013') {
            *q++ = '\\';
            *q++ = 'v';
        }
        else if (c == '\010') {
            *q++ = '\\';
            *q++ = 'b';
        }
        else if (c == '\007') {
            *q++ = '\\';
            *q++ = 'a';
        }
        else if (c == '\033') {
            *q++ = '\\';
            *q++ = 'e';
        }
        else if (ISPRINT(c)) {
            *q++ = c;
        }
        else {
            *q++ = '\\';
            if (u8) {
                int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
                if (MBCLEN_CHARFOUND_P(n)) {
                    int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
                    p += n;
                    if (cc <= 0xFFFF)
                        snprintf(q, qend-q, "u%04X", cc);    /* \uXXXX */
                    else
                        snprintf(q, qend-q, "u{%X}", cc);  /* \u{XXXXX} or \u{XXXXXX} */
                    q += strlen(q);
                    continue;
                }
            }
            snprintf(q, qend-q, "x%02X", c);
            q += 3;
        }
    }
    *q++ = '"';
    *q = '\0';
    if (!rb_enc_asciicompat(enc)) {
        snprintf(q, qend-q, nonascii_suffix, enc->name);
        encidx = rb_ascii8bit_encindex();
    }
    /* result from dump is ASCII */
    rb_enc_associate_index(result, encidx);
    ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT);
    return result;
}

Для обычной строки этот метод, +String#dump+, возвращает версию self, пригодную для печати и состоящую только из символов ASCII, заключённую в двойные кавычки.

Для дампированной строки метод String#undump является обратным к +String#dump+; он возвращает «восстановленную» версию self, отменяя все изменения, внесённые при создании дампа.

В простейшем случае дампированная строка содержит исходную строку, заключённую в двойные кавычки; этот пример выполнен в irb (интерактивной среде Ruby), где для вывода результатов используется метод ‘inspect`:

s = 'hello'   # => "hello"
s.dump        # => "\"hello\""
s.dump.undump # => "hello"

Обратите внимание, что во второй строке выше:

  • Внешние двойные кавычки добавлены inspect и не являются частью вывода dump.

  • Внутренние двойные кавычки являются частью вывода dump и экранируются inspect, поскольку находятся внутри внешних двойных кавычек.

Чтобы избежать путаницы, воспользуемся вспомогательным методом, который убирает внешние двойные кавычки:

def dump(s)
  print "String:   ", s, "\n"
  print "Dumped:   ", s.dump, "\n"
  print "Undumped: ", s.dump.undump, "\n"
end

Для строки 'hello' мы увидим:

String:    hello
Dumped:    "hello"
Undumped:  hello

В дампе некоторые специальные символы экранируются:

String:    "
Dumped:    "\""
Undumped:  "

String:    \
Dumped:    "\\"
Undumped:  \

В дампе непечатаемые символы заменяются печатаемыми; к непечатаемым символам относятся пробельные символы (кроме самого пробела). Здесь мы видим порядковые номера этих символов и поясняющий текст:

h = {
   7 => 'Alert (BEL)',
   8 => 'Backspace (BS)',
   9 => 'Horizontal tab (HT)',
  10 => 'Linefeed (LF)',
  11 => 'Vertical tab (VT)',
  12 => 'Formfeed (FF)',
  13 => 'Carriage return (CR)'
}

В этом примере дампированный вывод печатается методом inspect, поэтому содержит как внешние двойные кавычки, так и экранированные внутренние двойные кавычки:

s = ''
h.keys.each {|i| s << i } # => [7, 8, 9, 10, 11, 12, 13]
s                         # => "\a\b\t\n\v\f\r"
s.dump                    # => "\"\\a\\b\\t\\n\\v\\f\\r\""

Если self закодирована в UTF-8 и содержит символы Unicode, каждый символ Unicode преобразуется в escape-последовательность Unicode:

String:    тест
Dumped:    "\u0442\u0435\u0441\u0442"
Undumped:  тест

String:    こんにちは
Dumped:    "\u3053\u3093\u306B\u3061\u306F"
Undumped:  こんにちは

Если кодировка self несовместима с ASCII (то есть если self.encoding.ascii_compatible? возвращает false), каждый совместимый с ASCII байт выводится как символ ASCII, а все остальные байты — в шестнадцатеричном формате; также добавляется .dup.force_encoding(\"encoding\"), где <encoding> — это self.encoding.name:

String:    hello
Dumped:    "\xFE\xFF\x00h\x00e\x00l\x00l\x00o".dup.force_encoding("UTF-16")
Undumped:  hello

String:    тест
Dumped:    "\xFE\xFF\x04B\x045\x04A\x04B".dup.force_encoding("UTF-16")
Undumped:  тест

String:    こんにちは
Dumped:    "\xFE\xFF0S0\x930k0a0o".dup.force_encoding("UTF-16")
Undumped:  こんにちは
each_byte {|byte| ... } → self Показать исходный код
each_byte → enumerator
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);
}

Если передан блок, вызывает его для каждого следующего байта из self; возвращает self:

a = []
'hello'.each_byte {|byte| a.push(byte) }     # Five 1-byte characters.
a # => [104, 101, 108, 108, 111]
a = []
'тест'.each_byte {|byte| a.push(byte) }      # Four 2-byte characters.
a # => [209, 130, 208, 181, 209, 129, 209, 130]
a = []
'こんにちは'.each_byte {|byte| a.push(byte) }  # Five 3-byte characters.
a # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]

Если блок не передан, возвращает перечислитель.

См. также: Итерация.

each_char {|char| ... } → self Показать исходный код
each_char → enumerator
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);
}

Если передан блок, вызывает его для каждого следующего символа из self; возвращает self:

a = []
'hello'.each_char do |char|
  a.push(char)
end
a # => ["h", "e", "l", "l", "o"]
a = []
'тест'.each_char do |char|
  a.push(char)
end
a # => ["т", "е", "с", "т"]
a = []
'こんにちは'.each_char do |char|
  a.push(char)
end
a # => ["こ", "ん", "に", "ち", "は"]

Если блок не передан, возвращает перечислитель.

См. также: Итерация.

each_codepoint {|codepoint| ... } → self Показать исходный код
each_codepoint → enumerator
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);
}

Если передан блок, вызывает его для каждой следующей кодовой точки из self; каждая кодовая точка — это целочисленное значение символа; возвращает self:

a = []
'hello'.each_codepoint do |codepoint|
  a.push(codepoint)
end
a # => [104, 101, 108, 108, 111]
a = []
'тест'.each_codepoint do |codepoint|
  a.push(codepoint)
end
a # => [1090, 1077, 1089, 1090]
a = []
'こんにちは'.each_codepoint do |codepoint|
  a.push(codepoint)
end
a # => [12371, 12435, 12395, 12385, 12399]

Если блок не передан, возвращает перечислитель.

См. также: Итерация.

each_grapheme_cluster {|grapheme_cluster| ... } → self Показать исходный код
each_grapheme_cluster → enumerator
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);
}

Если передан блок, вызывает его для каждого следующего кластера графем из self (см. границы кластеров графем Unicode); возвращает self:

a = []
'hello'.each_grapheme_cluster do |grapheme_cluster|
  a.push(grapheme_cluster)
end
a  # => ["h", "e", "l", "l", "o"]

a = []
'тест'.each_grapheme_cluster do |grapheme_cluster|
  a.push(grapheme_cluster)
end
a # => ["т", "е", "с", "т"]

a = []
'こんにちは'.each_grapheme_cluster do |grapheme_cluster|
  a.push(grapheme_cluster)
end
a # => ["こ", "ん", "に", "ち", "は"]

Если блок не передан, возвращает перечислитель.

См. также: Итерация.

each_line(record_separator = $/, chomp: false) {|substring| ... } → self Показать исходный код
each_line(record_separator = $/, chomp: false) → enumerator
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);
}

Если передан блок, формирует подстроки (строки), полученные при разделении self в каждом месте вхождения заданного record_separator; передаёт каждую строку блоку; возвращает self.

С разделителем record_separator по умолчанию:

$/ # => "\n"
s = <<~EOT
This is the first line.
This is line two.

This is line four.
This is line five.
EOT
s.each_line {|line| p line }

Вывод:

"This is the first line.\n"
"This is line two.\n"
"\n"
"This is line four.\n"
"This is line five.\n"

С другим значением record_separator:

record_separator = ' is '
s.each_line(record_separator) {|line| p line }

Вывод:

"This is "
"the first line.\nThis is "
"line two.\n\nThis is "
"line four.\nThis is "
"line five.\n"

Если chomp равен true, удаляет конечный record_separator из каждой строки:

s.each_line(chomp: true) {|line| p line }

Вывод:

"This is the first line."
"This is line two."
""
"This is line four."
"This is line five."

Если в качестве record_separator указана пустая строка, формирует и передаёт «абзацы», разделяя текст при каждом вхождении двух или более символов новой строки:

record_separator = ''
s.each_line(record_separator) {|line| p line }

Вывод:

"This is the first line.\nThis is line two.\n\n"
"This is line four.\nThis is line five.\n"

Если блок не передан, возвращает перечислитель.

См. также: Итерация.

empty? → true or false Показать исходный код
static VALUE
rb_str_empty(VALUE str)
{
    return RBOOL(RSTRING_LEN(str) == 0);
}

Возвращает, равна ли длина self нулю:

'hello'.empty? # => false
' '.empty? # => false
''.empty? # => true

См. также: Проверка.

encode(dst_encoding = Encoding.default_internal, **enc_opts) → string Показать исходный код
encode(dst_encoding, src_encoding, **enc_opts) → string
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);
}

Возвращает копию self, преобразованную в соответствии с dst_encoding; см. Кодировки.

По умолчанию вызывает исключение, если self содержит недопустимый байт или символ, не определённый в dst_encoding; это поведение можно изменить с помощью параметров кодирования; см. ниже.

Без аргументов:

  • Используется та же кодировка, если Encoding.default_internal равен nil (значение по умолчанию):

    Encoding.default_internal # => nil
    s = "Ruby\x99".force_encoding('Windows-1252')
    s.encoding                # => #<Encoding:Windows-1252>
    s.bytes                   # => [82, 117, 98, 121, 153]
    t = s.encode              # => "Ruby\x99"
    t.encoding                # => #<Encoding:Windows-1252>
    t.bytes                   # => [82, 117, 98, 121, 226, 132, 162]
    
  • В противном случае используется кодировка Encoding.default_internal:

    Encoding.default_internal = 'UTF-8'
    t = s.encode              # => "Ruby™"
    t.encoding                # => #<Encoding:UTF-8>
    

Если указан только аргумент dst_encoding, используется эта кодировка:

s = "Ruby\x99".force_encoding('Windows-1252')
s.encoding            # => #<Encoding:Windows-1252>
t = s.encode('UTF-8') # => "Ruby™"
t.encoding            # => #<Encoding:UTF-8>

Если указаны аргументы dst_encoding и src_encoding, self интерпретируется с использованием src_encoding, а новая строка кодируется с использованием dst_encoding:

s = "Ruby\x99"
t = s.encode('UTF-8', 'Windows-1252') # => "Ruby™"
t.encoding                            # => #<Encoding:UTF-8>

Необязательные именованные аргументы enc_opts задают параметры кодирования; см. Параметры кодирования.

Обратите внимание: если не указан параметр invalid: :replace, преобразование из кодировки enc в ту же кодировку enc (независимо от того, задан ли enc явно или неявно) не выполняется; строка просто копируется без изменений, и исключения не вызываются, даже если она содержит недопустимые байты.

См. также: Преобразование в новую строку.

encode!(dst_encoding = Encoding.default_internal, **enc_opts) → self Показать исходный код
encode!(dst_encoding, src_encoding, **enc_opts) → self
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);
}

Как encode, но изменения кодировки применяются к self; возвращает self.

См. также: Изменение.

encoding → encoding Показать исходный код
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, представляющий кодировку self; см. Кодировки.

См. также: Проверка.

end_with?(*strings) → true or false Показать исходный код
static VALUE
rb_str_end_with(int argc, VALUE *argv, VALUE str)
{
    int i;

    for (i=0; i<argc; i++) {
        VALUE tmp = argv[i];
        const char *p, *s, *e;
        long slen, tlen;
        rb_encoding *enc;

        StringValue(tmp);
        enc = rb_enc_check(str, tmp);
        if ((tlen = RSTRING_LEN(tmp)) == 0) return Qtrue;
        if ((slen = RSTRING_LEN(str)) < tlen) continue;
        p = RSTRING_PTR(str);
        e = p + slen;
        s = e - tlen;
        if (!at_char_boundary(p, s, e, enc))
            continue;
        if (memcmp(s, RSTRING_PTR(tmp), tlen) == 0)
            return Qtrue;
    }
    return Qfalse;
}

Возвращает, оканчивается ли self любой из заданных strings:

'foo'.end_with?('oo')         # => true
'foo'.end_with?('bar', 'oo')  # => true
'foo'.end_with?('bar', 'baz') # => false
'foo'.end_with?('')           # => true
'тест'.end_with?('т')         # => true
'こんにちは'.end_with?('は')   # => true

См. также: Проверка.

eql?(object) → true or false Показать исходный код
VALUE
rb_str_eql(VALUE str1, VALUE str2)
{
    if (str1 == str2) return Qtrue;
    if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
    return rb_str_eql_internal(str1, str2);
}

Возвращает, имеют ли self и object одинаковую длину и содержимое:

s = 'foo'
s.eql?('foo')  # => true
s.eql?('food') # => false
s.eql?('FOO')  # => false

Возвращает false, если кодировки двух строк несовместимы:

s0 = "äöü"                           # => "äöü"
s1 = s0.encode(Encoding::ISO_8859_1) # => "\xE4\xF6\xFC"
s0.encoding                          # => #<Encoding:UTF-8>
s1.encoding                          # => #<Encoding:ISO-8859-1>
s0.eql?(s1)                          # => false

См. Кодировки.

См. также: Проверка.

force_encoding(encoding) → self Показать исходный код
static VALUE
rb_str_force_encoding(VALUE str, VALUE enc)
{
    str_modifiable(str);

    rb_encoding *encoding = rb_to_encoding(enc);
    int idx = rb_enc_to_index(encoding);

    // If the encoding is unchanged, we do nothing.
    if (ENCODING_GET(str) == idx) {
        return str;
    }

    rb_enc_associate_index(str, idx);

    // If the coderange was 7bit and the new encoding is ASCII-compatible
    // we can keep the coderange.
    if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT && encoding && rb_enc_asciicompat(encoding)) {
        return str;
    }

    ENC_CODERANGE_CLEAR(str);
    return str;
}

Изменяет кодировку self на указанную encoding, которой может быть название кодировки в виде строки или объект Encoding; базовые байты не изменяются; возвращает self:

s = 'łał'
s.bytes                   # => [197, 130, 97, 197, 130]
s.encoding                # => #<Encoding:UTF-8>
s.force_encoding('ascii') # => "\xC5\x82a\xC5\x82"
s.encoding                # => #<Encoding:US-ASCII>
s.valid_encoding?         # => true
s.bytes                   # => [197, 130, 97, 197, 130]

Изменение выполняется, даже если указанная encoding недопустима для self (как и в приведённом выше примере):

s.valid_encoding?         # => false

См. Кодировки.

Связанный раздел: Изменение.

getbyte(index) → integer or nil Показать исходный код
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, отсчитываемому с нуля, в виде целого числа:

s = 'foo'
s.getbyte(0)    # => 102
s.getbyte(1)    # => 111
s.getbyte(2)    # => 111

Если index отрицателен, отсчёт ведётся от конца:

s.getbyte(-3) # => 102

Возвращает nil, если index выходит за допустимые границы:

s.getbyte(3)  # => nil
s.getbyte(-4) # => nil

Другие примеры:

s = 'тест'
s.bytes      # => [209, 130, 208, 181, 209, 129, 209, 130]
s.getbyte(2) # => 208
s = 'こんにちは'
s.bytes      # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
s.getbyte(2) # => 147

Связанный раздел: Преобразование в нестроковое значение.

grapheme_clusters → array_of_grapheme_clusters Показать исходный код
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);
}

Возвращает массив графемных кластеров в self (см. Границы графемных кластеров Unicode):

s = "ä-pqr-b̈-xyz-c̈"
s.size                   # => 16
s.bytesize               # => 19
s.grapheme_clusters.size # => 13
s.grapheme_clusters
# => ["ä", "-", "p", "q", "r", "-", "b̈", "-", "x", "y", "z", "-", "c̈"]

Подробности:

s = "ä"
s.grapheme_clusters             # => ["ä"]           # One grapheme cluster.
s.bytes                         # => [97, 204, 136]  # Three bytes.
s.chars                         # => ["a", "̈"]       # Two characters.
s.chars.map {|char| char.ord }  # => [97, 776]       # Their values.

Связанный раздел: Преобразование в нестроковое значение.

gsub(pattern, replacement) → new_string Показать исходный код
gsub(pattern) {|match| ... } → new_string
gsub(pattern) → enumerator
static VALUE
rb_str_gsub(int argc, VALUE *argv, VALUE str)
{
    return str_gsub(argc, argv, str, 0);
}

Возвращает копию self, в которой заменены ноль или более подстрок.

Аргумент pattern может быть строкой или Regexp; аргумент replacement может быть строкой или Hash. Возможность использовать аргументы разных типов делает этот метод очень универсальным.

Ниже приведены несколько простых примеров; дополнительные примеры см. в разделе Методы подстановки.

Если переданы аргументы pattern и строка replacement, каждая совпавшая подстрока заменяется указанной строкой replacement:

s = 'abracadabra'
s.gsub('ab', 'AB')   # => "ABracadABra"
s.gsub(/[a-c]/, 'X') # => "XXrXXXdXXrX"

Если переданы аргументы pattern и хеш replacement, каждая совпавшая подстрока заменяется значением из указанного хеша replacement или удаляется:

h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
s.gsub(/[a-c]/, h) # => "ABrACAdABrA"  # 'a', 'b', 'c' replaced.
s.gsub(/[a-d]/, h) # => "ABrACAABrA"   # 'd' removed.

Если передан аргумент pattern и блок, блок вызывается для каждой совпавшей подстроки; эта подстрока заменяется возвращаемым блоком значением:

s.gsub(/[a-d]/) {|substring| substring.upcase }
# => "ABrACADABrA"

Если передан аргумент pattern без блока, возвращается новый Enumerator.

Связанный раздел: Преобразование в новую строку.

gsub!(pattern, replacement) → self or nil Показать исходный код
gsub!(pattern) {|match| ... } → self or nil
gsub!(pattern) → an_enumerator
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, но:

  • Выполняет подстановки непосредственно в self (а не в копии self).

  • Возвращает self, если были удалены какие-либо символы, и nil в противном случае.

Связанный раздел: Изменение.

hash → integer Показать исходный код
static VALUE
rb_str_hash_m(VALUE str)
{
    st_index_t hval = rb_str_hash(str);
    return ST2FIX(hval);
}

Возвращает целочисленное хеш-значение для self.

Два объекта String с одинаковым содержимым и совместимыми кодировками также имеют одинаковые хеш-значения; см. Object#hash и Кодировки:

s = 'foo'
h = s.hash       # => -569050784
h == 'foo'.hash  # => true
h == 'food'.hash # => false
h == 'FOO'.hash  # => false

s0 = "äöü"
s1 = s0.encode(Encoding::ISO_8859_1)
s0.encoding        # => #<Encoding:UTF-8>
s1.encoding        # => #<Encoding:ISO-8859-1>
s0.hash == s1.hash # => false

Связанный раздел: Запросы.

hex → integer Показать исходный код
static VALUE
rb_str_hex(VALUE str)
{
    return rb_str_to_inum(str, 16, FALSE);
}

Интерпретирует начальную подстроку self как шестнадцатеричное число, возможно со знаком; возвращает его значение в виде целого числа.

Начальная подстрока интерпретируется как шестнадцатеричное число, если она начинается с:

  • Одного или нескольких символов, представляющих шестнадцатеричные цифры (каждая из диапазонов '0'..'9', 'a'..'f' или 'A'..'F'); интерпретация строки заканчивается на первом символе, который не является шестнадцатеричной цифрой:

    'f'.hex        # => 15
    '11'.hex       # => 17
    'FFF'.hex      # => 4095
    'fffg'.hex     # => 4095
    'foo'.hex      # => 15   # 'f' hexadecimal, 'oo' not.
    'bar'.hex      # => 186  # 'ba' hexadecimal, 'r' not.
    'deadbeef'.hex # => 3735928559
    
  • '0x' или '0X', за которыми следуют одна или несколько шестнадцатеричных цифр:

    '0xfff'.hex    # => 4095
    '0xfffg'.hex   # => 4095
    

Перед любой из указанных выше последовательностей может стоять '-', который меняет знак интерпретируемого значения на противоположный:

'-fff'.hex      # => -4095
'-0xFFF'.hex    # => -4095

Для любой подстроки, не описанной выше, возвращает ноль:

'xxx'.hex     # => 0
''.hex        # => 0

Обратите внимание: в отличие от oct, этот метод интерпретирует только шестнадцатеричную запись, но не двоичную, восьмеричную или десятичную:

'0b111'.hex   # => 45329
'0o777'.hex   # => 0
'0d999'.hex   # => 55705

Связанный раздел: см. Преобразование в нестроковое значение.

include?(other_string) → true or false Показать исходный код
VALUE
rb_str_include(VALUE str, VALUE arg)
{
    long i;

    StringValue(arg);
    i = rb_str_index(str, arg, 0);

    return RBOOL(i != -1);
}

Возвращает значение, указывающее, содержит ли self строку other_string:

s = 'bar'
s.include?('ba')  # => true
s.include?('ar')  # => true
s.include?('bar') # => true
s.include?('a')   # => true
s.include?('')    # => true
s.include?('foo') # => false

Связанный раздел: Запросы.

index(pattern, offset = 0) → integer or nil Показать исходный код
static VALUE
rb_str_index_m(int argc, VALUE *argv, VALUE str)
{
    VALUE sub;
    VALUE initpos;
    rb_encoding *enc = STR_ENC_GET(str);
    long pos;

    if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
        long slen = str_strlen(str, enc); /* str's enc */
        pos = NUM2LONG(initpos);
        if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
            if (RB_TYPE_P(sub, T_REGEXP)) {
                rb_backref_set(Qnil);
            }
            return Qnil;
        }
    }
    else {
        pos = 0;
    }

    if (RB_TYPE_P(sub, T_REGEXP)) {
        pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
                         enc, single_byte_optimizable(str));

        if (rb_reg_search(sub, str, pos, 0) >= 0) {
            VALUE match = rb_backref_get();
            struct re_registers *regs = RMATCH_REGS(match);
            pos = rb_str_sublen(str, BEG(0));
            return LONG2NUM(pos);
        }
    }
    else {
        StringValue(sub);
        pos = rb_str_index(str, sub, pos);
        if (pos >= 0) {
            pos = rb_str_sublen(str, pos);
            return LONG2NUM(pos);
        }
    }
    return Qnil;
}

Возвращает целочисленную позицию первой подстроки, соответствующей заданному аргументу pattern, или nil, если совпадений нет.

Если pattern — строка, возвращает индекс первой совпавшей подстроки в self:

'foo'.index('f')         # => 0
'foo'.index('o')         # => 1
'foo'.index('oo')        # => 1
'foo'.index('ooo')       # => nil
'тест'.index('с')        # => 2  # Characters, not bytes.
'こんにちは'.index('ち')  # => 3

Если pattern — это Regexp, возвращает индекс первого совпадения в self:

'foo'.index(/o./) # => 1
'foo'.index(/.o/) # => 0

Если offset неотрицателен, поиск начинается с позиции offset; возвращаемый индекс отсчитывается от начала self:

'bar'.index('r', 0)        # => 2
'bar'.index('r', 1)        # => 2
'bar'.index('r', 2)        # => 2
'bar'.index('r', 3)        # => nil
'bar'.index(/[r-z]/, 0)    # => 2
'тест'.index('с', 1)       # => 2
'тест'.index('с', 2)       # => 2
'тест'.index('с', 3)       # => nil  # Offset in characters, not bytes.
'こんにちは'.index('ち', 2) # => 3

При отрицательном целочисленном аргументе offset позиция поиска определяется отсчётом от конца self:

'foo'.index('o', -1)  # => 2
'foo'.index('o', -2)  # => 1
'foo'.index('o', -3)  # => 1
'foo'.index('o', -4)  # => nil
'foo'.index(/o./, -2) # => 1
'foo'.index(/.o/, -2) # => 1

Связанный раздел: Запросы.

initialize_copy
Псевдоним для: replace
insert(offset, other_string) → self Показать исходный код
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_update(str, pos, 0, str2);
    return str;
}

Вставляет указанную other_string в self; возвращает self.

Если указанная index неотрицательна, other_string вставляется по смещению index:

'foo'.insert(0, 'bar')       # => "barfoo"
'foo'.insert(1, 'bar')       # => "fbaroo"
'foo'.insert(3, 'bar')       # => "foobar"
'тест'.insert(2, 'bar')      # => "теbarст"  # Characters, not bytes.
'こんにちは'.insert(2, 'bar') # => "こんbarにちは"

Если index отрицательна, отсчёт ведётся от конца self, а other_string вставляется после указанного смещения:

'foo'.insert(-2, 'bar') # => "fobaro"

Связанный раздел: Изменение.

inspect → string Показать исходный код
VALUE
rb_str_inspect(VALUE str)
{
    int encidx = ENCODING_GET(str);
    rb_encoding *enc = rb_enc_from_index(encidx);
    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;
    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;
        }
        /* The special casing of 0x85 (NEXT_LINE) here is because
         * Oniguruma historically treats it as printable, but it
         * doesn't match the print POSIX bracket class or character
         * property in regexps.
         *
         * See Ruby Bug #16842 for details:
         * https://bugs.ruby-lang.org/issues/16842
         */
        if ((enc == resenc && rb_enc_isprint(c, enc) && c != 0x85) ||
            (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
            continue;
        }
        else {
            if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
            rb_str_buf_cat_escaped_char(result, c, unicode_p);
            prev = p;
            continue;
        }
    }
    if (p > prev) str_buf_cat(result, prev, p - prev);
    str_buf_cat2(result, "\"");

    return result;
}

Возвращает пригодное для печати представление self, заключённое в двойные кавычки.

Большинство печатных символов отображаются без изменений:

'abc'.inspect        # => "\"abc\""
'012'.inspect        # => "\"012\""
''.inspect           # => "\"\""
"\u000012".inspect   # => "\"\\u000012\""
'тест'.inspect       # => "\"тест\""
'こんにちは'.inspect  # => "\"こんにちは\""

Однако печатные символы двойной кавычки ('"') и обратной косой черты ('\') экранируются:

'"'.inspect  # => "\"\\\"\""
'\\'.inspect # => "\"\\\\\""

Непечатаемые символы — это символы ASCII со значениями в диапазоне 0..31, а также символ со значением 127.

Большинство таких символов отображаются следующим образом:

0.chr.inspect # => "\"\\x00\""
1.chr.inspect # => "\"\\x01\""
2.chr.inspect # => "\"\\x02\""
# ...

Однако некоторые из них имеют особое представление:

7.chr.inspect  # => "\"\\a\""  # BEL
8.chr.inspect  # => "\"\\b\""  # BS
9.chr.inspect  # => "\"\\t\""  # TAB
10.chr.inspect # => "\"\\n\""  # LF
11.chr.inspect # => "\"\\v\""  # VT
12.chr.inspect # => "\"\\f\""  # FF
13.chr.inspect # => "\"\\r\""  # CR
27.chr.inspect # => "\"\\e\""  # ESC

Связанный раздел: Преобразование в нестроковое значение.

intern → symbol Показать исходный код
VALUE
rb_str_intern(VALUE str)
{
    return sym_find_or_insert_dynamic_symbol(&ruby_global_symbols, str);
}

Возвращает объект Symbol, созданный на основе self; если такого объекта ещё не было, он создаётся:

'foo'.intern       # => :foo
'тест'.intern      # => :тест
'こんにちは'.intern # => :こんにちは

Связанный раздел: Преобразование в нестроковое значение.

Также имеет псевдоним: to_sym
length → integer Показать исходный код
VALUE
rb_str_length(VALUE str)
{
    return LONG2NUM(str_strlen(str, NULL));
}

Возвращает количество символов (не байтов) в self:

'foo'.length        # => 3
'тест'.length       # => 4
'こんにちは'.length  # => 5

Сравните с String#bytesize:

'foo'.bytesize        # => 3
'тест'.bytesize       # => 8
'こんにちは'.bytesize  # => 15

Связанный раздел: Запросы.

Также имеет псевдоним: size
lines(record_separator = $/, chomp: false) → array_of_strings Показать исходный код
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);
}

Возвращает подстроки («строки») из self в соответствии с заданными аргументами:

s = <<~EOT
This is the first line.
This is line two.

This is line four.
This is line five.
EOT

Со значениями аргументов по умолчанию:

$/ # => "\n"
s.lines
# =>
["This is the first line.\n",
 "This is line two.\n",
 "\n",
 "This is line four.\n",
 "This is line five.\n"]

С другим record_separator:

record_separator = ' is '
s.lines(record_separator)
# =>
["This is ",
 "the first line.\nThis is ",
 "line two.\n\nThis is ",
 "line four.\nThis is ",
 "line five.\n"]

Если ключевой аргумент chomp задан как true, удаляет завершающий символ новой строки из каждой строки:

s.lines(chomp: true)
# =>
["This is the first line.",
 "This is line two.",
 "",
 "This is line four.",
 "This is line five."]

Связано: см. Преобразование в нестроковый объект.

ljust(width, pad_string = ' ') → new_string Показать исходный код
static VALUE
rb_str_ljust(int argc, VALUE *argv, VALUE str)
{
    return rb_str_justify(argc, argv, str, 'l');
}

Возвращает копию self, выровненную по левому краю и, если необходимо, дополненную справа символами pad_string:

'hello'.ljust(10)       # => "hello     "
'  hello'.ljust(10)     # => "  hello   "
'hello'.ljust(10, 'ab') # => "helloababa"
'тест'.ljust(10)        # => "тест      "
'こんにちは'.ljust(10)   # => "こんにちは     "

Если width <= self.length, возвращает копию self:

'hello'.ljust(5)  # => "hello"
'hello'.ljust(1)  # => "hello"  # Does not truncate to width.

Связано: см. Преобразование в новую строку.

lstrip(*selectors) → new_string Показать исходный код
static VALUE
rb_str_lstrip(int argc, VALUE *argv, VALUE str)
{
    char *start;
    long len, loffset;

    RSTRING_GETMEM(str, start, len);
    if (argc > 0) {
        char table[TR_TABLE_SIZE];
        VALUE del = 0, nodel = 0;

        tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
        loffset = lstrip_offset_table(str, start, start+len, STR_ENC_GET(str), table, del, nodel);
    }
    else {
        loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
    }
    if (loffset <= 0) return str_duplicate(rb_cString, str);
    return rb_str_subseq(str, loffset, len - loffset);
}

Возвращает копию self без начальных пробельных символов; см. Пробельные символы в строках:

whitespace = "\x00\t\n\v\f\r "
s = whitespace + 'abc' + whitespace
# => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
s.lstrip
# => "abc\u0000\t\n\v\f\r "

Если заданы selectors, удаляет символы из selectors в начале self:

s = "---abc+++"
s.lstrip("-") # => "abc+++"

selectors должны быть допустимыми селекторами символов (см. Селекторы символов) и могут использовать любую допустимую форму, включая отрицание, диапазоны и escape-последовательности:

"01234abc56789".lstrip("0-9") # "abc56789"
"01234abc56789".lstrip("0-9", "^4-6") # "4abc56789"

Связано: см. Преобразование в новую строку.

lstrip!(*selectors) → self or nil Показать исходный код
static VALUE
rb_str_lstrip_bang(int argc, VALUE *argv, 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);
    if (argc > 0) {
        char table[TR_TABLE_SIZE];
        VALUE del = 0, nodel = 0;

        tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
        loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
    }
    else {
        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);
        TERM_FILL(start+len, rb_enc_mbminlen(enc));
        return str;
    }
    return Qnil;
}

Как String#lstrip, за исключением того, что:

  • Удаление выполняется непосредственно в self (а не в копии self).

  • Возвращает self, если были удалены какие-либо символы, и nil в противном случае.

Связано: см. Изменение.

match(pattern, offset = 0) → matchdata or nil Показать исходный код
match(pattern, offset = 0) {|matchdata| ... } → object
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;
}

Создаёт объект MatchData на основе self и заданных аргументов; обновляет глобальные переменные Regexp.

  • Вычисляет regexp, преобразуя pattern (если это ещё не Regexp).

    regexp = Regexp.new(pattern)
    
  • Вычисляет matchdata, которым будет либо объект MatchData, либо nil (см. Regexp#match):

    matchdata = regexp.match(self[offset..])
    

Если блок не задан, возвращает вычисленное matchdata или nil:

'foo'.match('f')    # => #<MatchData "f">
'foo'.match('o')    # => #<MatchData "o">
'foo'.match('x')    # => nil
'foo'.match('f', 1) # => nil
'foo'.match('o', 1) # => #<MatchData "o">

Если блок задан и вычисленное matchdata не равно nil, вызывает блок с matchdata и возвращает значение, возвращённое блоком:

'foo'.match(/o/) {|matchdata| matchdata } # => #<MatchData "o">

Если блок задан, а nil равно matchdata, блок не вызывается:

'foo'.match(/x/) {|matchdata| fail 'Cannot happen' } # => nil

Связано: см. Запросы.

match?(pattern, offset = 0) → true or false Показать исходный код
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);
}

Возвращает, найдено ли совпадение для self с заданными аргументами; не обновляет глобальные переменные Regexp.

Вычисляет regexp, преобразуя pattern (если это ещё не Regexp):

regexp = Regexp.new(pattern)

Возвращает true, если self[offset..].match(regexp) возвращает объект MatchData, и false в противном случае:

'foo'.match?(/o/) # => true
'foo'.match?('o') # => true
'foo'.match?(/x/) # => false
'foo'.match?('f', 1) # => false
'foo'.match?('o', 1) # => true

Связано: см. Запросы.

next
Псевдоним для: succ
next!
Псевдоним для: succ!
oct → integer Показать исходный код
static VALUE
rb_str_oct(VALUE str)
{
    return rb_str_to_inum(str, -8, FALSE);
}

Интерпретирует начальную подстроку self как восьмеричное, двоичное, десятичное или шестнадцатеричное число, возможно со знаком; возвращает её значение в виде целого числа.

Кратко:

# Interpreted as octal.
'777'.oct   # => 511
'777x'.oct  # => 511
'0777'.oct  # => 511
'0o777'.oct # => 511
'-777'.oct  # => -511
# Not interpreted as octal.
'0b111'.oct # => 7     # Interpreted as binary.
'0d999'.oct # => 999   # Interpreted as decimal.
'0xfff'.oct # => 4095  # Interpreted as hexadecimal.

Начальная подстрока интерпретируется как восьмеричное число, если начинается с:

  • Одного или нескольких символов, представляющих восьмеричные цифры (каждая в диапазоне '0'..'7'); интерпретируемая строка заканчивается на первом символе, не являющемся восьмеричной цифрой:

    '7'.oct      @ => 7
    '11'.oct     # => 9
    '777'.oct    # => 511
    '0777'.oct   # => 511
    '7778'.oct   # => 511
    '777x'.oct   # => 511
  • '0o', за которым следует одна или несколько восьмеричных цифр:

    '0o777'.oct  # => 511
    '0o7778'.oct # => 511
    

Начальная подстрока не интерпретируется как восьмеричное число, если начинается с:

  • '0b', за которым следует один или несколько символов, представляющих двоичные цифры (каждая в диапазоне '0'..'1'); интерпретируемая строка заканчивается на первом символе, не являющемся двоичной цифрой. Строка интерпретируется как последовательность двоичных цифр (основание 2):

    '0b111'.oct  # => 7
    '0b1112'.oct # => 7
    
  • '0d', за которым следует один или несколько символов, представляющих десятичные цифры (каждая в диапазоне '0'..'9'); интерпретируемая строка заканчивается на первом символе, не являющемся десятичной цифрой. Строка интерпретируется как последовательность десятичных цифр (основание 10):

    '0d999'.oct  # => 999
    '0d999x'.oct # => 999
    
  • '0x', за которым следует один или несколько символов, представляющих шестнадцатеричные цифры (каждая в одном из диапазонов '0'..'9', 'a'..'f' или 'A'..'F'); интерпретируемая строка заканчивается на первом символе, не являющемся шестнадцатеричной цифрой. Строка интерпретируется как последовательность шестнадцатеричных цифр (основание 16):

    '0xfff'.oct  # => 4095
    '0xfffg'.oct # => 4095
    

К любой из описанных выше форм может быть добавлен префикс '-', который меняет знак интерпретируемого значения на противоположный:

'-777'.oct   # => -511
'-0777'.oct  # => -511
'-0b111'.oct # => -7
'-0xfff'.oct # => -4095

Для любой подстроки, не описанной выше, возвращает ноль:

'foo'.oct      # => 0
''.oct         # => 0

Связано: см. Преобразование в нестроковый объект.

ord → integer Показать исходный код
static 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);
}

Возвращает целочисленный код первого символа self:

'h'.ord         # => 104
'hello'.ord     # => 104
'тест'.ord      # => 1090
'こんにちは'.ord  # => 12371

Связано: см. Преобразование в нестроковый объект.

partition(pattern) → [pre_match, first_match, post_match] Показать исходный код
static VALUE
rb_str_partition(VALUE str, VALUE sep)
{
    long pos;

    sep = get_pat_quoted(sep, 0);
    if (RB_TYPE_P(sep, T_REGEXP)) {
        if (rb_reg_search(sep, str, 0, 0) < 0) {
            goto failed;
        }
        VALUE match = rb_backref_get();
        struct re_registers *regs = RMATCH_REGS(match);

        pos = BEG(0);
        sep = rb_str_subseq(str, pos, END(0) - pos);
    }
    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)));

  failed:
    return rb_ary_new3(3, str_duplicate(rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
}

Возвращает массив из трёх элементов, содержащих подстроки self.

Если найдено совпадение с pattern, возвращает массив:

[pre_match, first_match, post_match]

где:

  • first_match — первое найденное совпадение.

  • pre_match и post_match — предшествующая и следующая подстроки.

Если совпадение с pattern не найдено, возвращает массив:

[self.dup, "", ""]

Обратите внимание: в приведённых ниже примерах возвращённая строка 'hello' является копией self, а не self.

Если pattern — это Regexp, выполняет эквивалент self.match(pattern) (также устанавливая переменные сопоставленных данных):

'hello'.partition(/h/)  # => ["", "h", "ello"]
'hello'.partition(/l/)  # => ["he", "l", "lo"]
'hello'.partition(/l+/) # => ["he", "ll", "o"]
'hello'.partition(/o/)  # => ["hell", "o", ""]
'hello'.partition(/^/)  # => ["", "", "hello"]
'hello'.partition(//)   # => ["", "", "hello"]
'hello'.partition(/$/)  # => ["hello", "", ""]
'hello'.partition(/x/)  # => ["hello", "", ""]

Если pattern не является Regexp, преобразует его в строку (если это ещё не строка), а затем выполняет эквивалент self.index(pattern) (и не устанавливает глобальные переменные сопоставленных данных):

'hello'.partition('h')     # => ["", "h", "ello"]
'hello'.partition('l')     # => ["he", "l", "lo"]
'hello'.partition('ll')    # => ["he", "ll", "o"]
'hello'.partition('o')     # => ["hell", "o", ""]
'hello'.partition('')      # => ["", "", "hello"]
'hello'.partition('x')     # => ["hello", "", ""]
'тест'.partition('т')      # => ["", "т", "ест"]
'こんにちは'.partition('に') # => ["こん", "に", "ちは"]

Связано: см. Преобразование в нестроковый объект.

prepend(*other_strings) → new_string Показать исходный код
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;
}

Добавляет в начало self конкатенацию заданных other_strings; возвращает self:

'baz'.prepend('foo', 'bar') # => "foobarbaz"

Связано: см. Изменение.

replace(other_string) → self Показать исходный код
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);
}

Заменяет содержимое self содержимым other_string; возвращает self:

s = 'foo'        # => "foo"
s.replace('bar') # => "bar"

Связано: см. Изменение.

Также имеет псевдоним: initialize_copy
reverse → new_string Показать исходный код
static VALUE
rb_str_reverse(VALUE str)
{
    rb_encoding *enc;
    VALUE rev;
    char *s, *e, *p;
    int cr;

    if (RSTRING_LEN(str) <= 1) return str_duplicate(rb_cString, str);
    enc = STR_ENC_GET(str);
    rev = rb_str_new(0, RSTRING_LEN(str));
    s = RSTRING_PTR(str); e = RSTRING_END(str);
    p = RSTRING_END(rev);
    cr = ENC_CODERANGE(str);

    if (RSTRING_LEN(str) > 1) {
        if (single_byte_optimizable(str)) {
            while (s < e) {
                *--p = *s++;
            }
        }
        else if (cr == ENC_CODERANGE_VALID) {
            while (s < e) {
                int clen = rb_enc_fast_mbclen(s, e, enc);

                p -= clen;
                memcpy(p, s, clen);
                s += clen;
            }
        }
        else {
            cr = rb_enc_asciicompat(enc) ?
                ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
            while (s < e) {
                int clen = rb_enc_mbclen(s, e, enc);

                if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN;
                p -= clen;
                memcpy(p, s, clen);
                s += clen;
            }
        }
    }
    STR_SET_LEN(rev, RSTRING_LEN(str));
    str_enc_copy_direct(rev, str);
    ENC_CODERANGE_SET(rev, cr);

    return rev;
}

Возвращает новую строку, содержащую символы self в обратном порядке.

'drawer'.reverse       # => "reward"
'reviled'.reverse      # => "deliver"
'stressed'.reverse     # => "desserts"
'semordnilaps'.reverse # => "spalindromes"

Связано: см. Преобразование в новую строку.

reverse! → self Показать исходный код
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;
}

Возвращает self с символами в обратном порядке:

'drawer'.reverse!       # => "reward"
'reviled'.reverse!      # => "deliver"
'stressed'.reverse!     # => "desserts"
'semordnilaps'.reverse! # => "spalindromes"

Связано: см. Изменение.

rindex(pattern, offset = self.length) → integer or nil Показать исходный код
static VALUE
rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
{
    VALUE sub;
    VALUE initpos;
    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, &initpos) == 2) {
        pos = NUM2LONG(initpos);
        if (pos < 0 && (pos += len) < 0) {
            if (RB_TYPE_P(sub, T_REGEXP)) {
                rb_backref_set(Qnil);
            }
            return Qnil;
        }
        if (pos > len) pos = len;
    }
    else {
        pos = len;
    }

    if (RB_TYPE_P(sub, T_REGEXP)) {
        /* enc = rb_enc_check(str, sub); */
        pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
                         enc, single_byte_optimizable(str));

        if (rb_reg_search(sub, str, pos, 1) >= 0) {
            VALUE match = rb_backref_get();
            struct re_registers *regs = RMATCH_REGS(match);
            pos = rb_str_sublen(str, BEG(0));
            return LONG2NUM(pos);
        }
    }
    else {
        StringValue(sub);
        pos = rb_str_rindex(str, sub, pos);
        if (pos >= 0) {
            pos = rb_str_sublen(str, pos);
            return LONG2NUM(pos);
        }
    }
    return Qnil;
}

Возвращает целочисленную позицию последней подстроки, соответствующей заданному аргументу pattern, или nil, если совпадений нет.

Если pattern — строка, возвращает индекс последней совпадающей подстроки в self:

'foo'.rindex('f')       # => 0
'foo'.rindex('o')       # => 2
'foo'.rindex('oo'       # => 1
'foo'.rindex('ooo')     # => nil
'тест'.rindex('т')      # => 3
'こんにちは'.rindex('ち') # => 3

Если pattern — Regexp, возвращает индекс последнего совпадения в self:

'foo'.rindex(/f/)   # => 0
'foo'.rindex(/o/)   # => 2
'foo'.rindex(/oo/)  # => 1
'foo'.rindex(/ooo/) # => nil

Если offset — неотрицательное число, оно задаёт максимальную начальную позицию в строке, с которой заканчивается поиск:

'foo'.rindex('o', 0) # => nil
'foo'.rindex('o', 1) # => 1
'foo'.rindex('o', 2) # => 2
'foo'.rindex('o', 3) # => 2

При отрицательном целочисленном аргументе offset позиция поиска определяется отсчётом назад от конца self:

'foo'.rindex('o', -1) # => 2
'foo'.rindex('o', -2) # => 1
'foo'.rindex('o', -3) # => nil
'foo'.rindex('o', -4) # => nil

Под последним совпадением понимается совпадение, начинающееся в самой поздней возможной позиции, а не самое длинное из совпадений:

'foo'.rindex(/o+/) # => 2
$~                 # => #<MatchData "o">

Чтобы получить последнее самое длинное совпадение, используйте отрицательный просмотр назад:

'foo'.rindex(/(?<!o)o+/) # => 1
$~                       # => #<MatchData "oo">

Или String#index с отрицательным просмотром вперёд.

'foo'.index(/o+(?!.*o)/) # => 1
$~                       # => #<MatchData "oo">

Связанные разделы: см. Поиск и запросы.

rjust(width, pad_string = ' ') → new_string Показать исходный код
static VALUE
rb_str_rjust(int argc, VALUE *argv, VALUE str)
{
    return rb_str_justify(argc, argv, str, 'r');
}

Возвращает копию self с выравниванием по правому краю.

Если целочисленный аргумент width больше размера self (в символах), возвращает новую строку длиной width, являющуюся копией self, выровненной по правому краю и дополненной слева символами pad_string:

'hello'.rjust(10)       # => "     hello"
'hello  '.rjust(10)     # => "   hello  "
'hello'.rjust(10, 'ab') # => "ababahello"
'тест'.rjust(10)        # => "      тест"
'こんにちは'.rjust(10)    # => "     こんにちは"

Если width <= self.size, возвращает копию self:

'hello'.rjust(5, 'ab')  # => "hello"
'hello'.rjust(1, 'ab')  # => "hello"

Связанные разделы: см. Преобразование в новую строку.

rpartition(pattern) → [pre_match, last_match, post_match] Показать исходный код
static VALUE
rb_str_rpartition(VALUE str, VALUE sep)
{
    long pos = RSTRING_LEN(str);

    sep = get_pat_quoted(sep, 0);
    if (RB_TYPE_P(sep, T_REGEXP)) {
        if (rb_reg_search(sep, str, pos, 1) < 0) {
            goto failed;
        }
        VALUE match = rb_backref_get();
        struct re_registers *regs = RMATCH_REGS(match);

        pos = BEG(0);
        sep = rb_str_subseq(str, pos, END(0) - pos);
    }
    else {
        pos = rb_str_sublen(str, pos);
        pos = rb_str_rindex(str, sep, pos);
        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)));
  failed:
    return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(rb_cString, str));
}

Возвращает массив из 3 элементов — подстрок self.

Ищет в self совпадение с pattern, отыскивая последнее совпадение.

Если pattern не найдено, возвращает массив:

["", "", self.dup]

Если pattern найдено, возвращает массив:

[pre_match, last_match, post_match]

где:

  • last_match — последняя найденная совпадающая подстрока.

  • pre_match и post_match — предшествующая и следующая подстроки.

Используется следующий шаблон:

  • само pattern, если это Regexp.

  • Regexp.quote(pattern), если pattern — строка.

Обратите внимание, что в приведённых ниже примерах возвращаемая строка 'hello' является копией self, а не self.

Если pattern — Regexp, выполняется поиск последней совпадающей подстроки (при этом также устанавливаются глобальные переменные с данными о совпадениях):

'hello'.rpartition(/l/)     # => ["hel", "l", "o"]
'hello'.rpartition(/ll/)    # => ["he", "ll", "o"]
'hello'.rpartition(/h/)     # => ["", "h", "ello"]
'hello'.rpartition(/o/)     # => ["hell", "o", ""]
'hello'.rpartition(//)      # => ["hello", "", ""]
'hello'.rpartition(/x/)     # => ["", "", "hello"]
'тест'.rpartition(/т/)      # => ["тес", "т", ""]
'こんにちは'.rpartition(/に/) # => ["こん", "に", "ちは"]

Если pattern не является Regexp, он преобразуется в строку (если ещё не является ею), после чего выполняется поиск последней совпадающей подстроки (при этом не устанавливаются глобальные переменные с данными о совпадениях):

'hello'.rpartition('l')     # => ["hel", "l", "o"]
'hello'.rpartition('ll')    # => ["he", "ll", "o"]
'hello'.rpartition('h')     # => ["", "h", "ello"]
'hello'.rpartition('o')     # => ["hell", "o", ""]
'hello'.rpartition('')      # => ["hello", "", ""]
'тест'.rpartition('т')      # => ["тес", "т", ""]
'こんにちは'.rpartition('に') # => ["こん", "に", "ちは"]

Связанные разделы: см. Преобразование в нестроковый объект.

rstrip(*selectors) → new_string Показать исходный код
static VALUE
rb_str_rstrip(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    char *start;
    long olen, roffset;

    enc = STR_ENC_GET(str);
    RSTRING_GETMEM(str, start, olen);
    if (argc > 0) {
        char table[TR_TABLE_SIZE];
        VALUE del = 0, nodel = 0;

        tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
        roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
    }
    else {
        roffset = rstrip_offset(str, start, start+olen, enc);
    }
    if (roffset <= 0) return str_duplicate(rb_cString, str);
    return rb_str_subseq(str, 0, olen-roffset);
}

Возвращает копию self с удалёнными конечными пробельными символами; см. раздел Пробельные символы в строках:

whitespace = "\x00\t\n\v\f\r "
s = whitespace + 'abc' + whitespace
s        # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
s.rstrip # => "\u0000\t\n\v\f\r abc"

Если указаны selectors, удаляет символы из selectors в конце self:

s = "---abc+++"
s.rstrip("+") # => "---abc"

selectors должны быть допустимыми селекторами символов (см. раздел Селекторы символов); можно использовать любую допустимую форму, включая отрицание, диапазоны и escape-последовательности:

"01234abc56789".rstrip("0-9") # "01234abc"
"01234abc56789".rstrip("0-9", "^4-6") # "01234abc56"

Связанные разделы: см. Преобразование в новую строку.

rstrip!(*selectors) → self or nil Показать исходный код
static VALUE
rb_str_rstrip_bang(int argc, VALUE *argv, 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);
    if (argc > 0) {
        char table[TR_TABLE_SIZE];
        VALUE del = 0, nodel = 0;

        tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
        roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
    }
    else {
        roffset = rstrip_offset(str, start, start+olen, enc);
    }
    if (roffset > 0) {
        long len = olen - roffset;

        STR_SET_LEN(str, len);
        TERM_FILL(start+len, rb_enc_mbminlen(enc));
        return str;
    }
    return Qnil;
}

Работает как String#rstrip, за исключением того, что:

  • Удаление выполняется непосредственно в self (а не в копии self).

  • Возвращает self, если были удалены какие-либо символы, и nil в противном случае.

Связанные разделы: см. Изменение.

scan(pattern) → array_of_results Показать исходный код
scan(pattern) {|result| ... } → self
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;
}

Сопоставляет шаблон с self:

  • Если pattern — Regexp, в качестве шаблона используется само pattern.

  • Если pattern — строка, в качестве шаблона используется Regexp.quote(pattern).

Создаёт коллекцию результатов поиска и обновляет глобальные переменные, связанные с регулярными выражениями:

  • Если шаблон не содержит групп, каждый результат — это совпавшая подстрока.

  • Если шаблон содержит группы, каждый результат — это массив, содержащий совпавшую подстроку для каждой группы.

Если блок не задан, возвращает массив результатов:

'cruel world'.scan(/\w+/)      # => ["cruel", "world"]
'cruel world'.scan(/.../)      # => ["cru", "el ", "wor"]
'cruel world'.scan(/(...)/)    # => [["cru"], ["el "], ["wor"]]
'cruel world'.scan(/(..)(..)/) # => [["cr", "ue"], ["l ", "wo"]]
'тест'.scan(/../)              # => ["те", "ст"]
'こんにちは'.scan(/../)         # => ["こん", "にち"]
'abracadabra'.scan('ab')       # => ["ab", "ab"]
'abracadabra'.scan('nosuch')   # => []

Если блок задан, вызывает его для каждого результата и возвращает self:

'cruel world'.scan(/\w+/) {|w| p w }
# => "cruel"
# => "world"
'cruel world'.scan(/(.)(.)/) {|x, y| p [x, y] }
# => ["c", "r"]
# => ["u", "e"]
# => ["l", " "]
# => ["w", "o"]
# => ["r", "l"]

Связанные разделы: см. Преобразование в нестроковый объект.

scrub(replacement_string = default_replacement_string) → new_string Показать исходный код
scrub{|sequence| ... } → new_string
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) ? str_duplicate(rb_cString, str): new;
}

Возвращает копию self, в которой каждая недопустимая последовательность байтов заменена указанной replacement_string.

Если блок не задан, заменяет каждую недопустимую последовательность указанной default_replacement_string (по умолчанию — "�" для кодировки Unicode и '?' в остальных случаях):

"foo\x81\x81bar"scrub                             # => "foo��bar"
"foo\x81\x81bar".force_encoding('US-ASCII').scrub # => "foo??bar"
"foo\x81\x81bar".scrub('xyzzy')                   # => "fooxyzzyxyzzybar"

Если блок задан, вызывает его для каждой недопустимой последовательности и заменяет эту последовательность значением, возвращённым блоком:

"foo\x81\x81bar".scrub {|sequence| p sequence; 'XYZZY' } # => "fooXYZZYXYZZYbar"

Результат:

"\x81"
"\x81"

Связанные разделы: см. Преобразование в новую строку.

scrub!(replacement_string = default_replacement_string) → self Показать исходный код
scrub!{|sequence| ... } → self
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;
}

Работает как String#scrub, за исключением того, что:

  • Все замены выполняются непосредственно в self.

  • Возвращает self.

Связанные разделы: см. Изменение.

setbyte(index, integer) → integer Показать исходный код
VALUE
rb_str_setbyte(VALUE str, VALUE index, VALUE value)
{
    long pos = NUM2LONG(index);
    long len = RSTRING_LEN(str);
    char *ptr, *head, *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;

    VALUE v = rb_to_int(value);
    VALUE w = rb_int_and(v, INT2FIX(0xff));
    char byte = (char)(NUM2INT(w) & 0xFF);

    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; возвращает integer:

s = 'xyzzy'
s.setbyte(2, 129) # => 129
s                 # => "xy\x81zy"

Связанные разделы: см. Изменение.

shellescape → string Показать исходный код
# File lib/shellwords.rb, line 238
def shellescape
  Shellwords.escape(self)
end

Экранирует str, чтобы его можно было безопасно использовать в командной строке оболочки Bourne.

Подробности см. в разделе Shellwords.shellescape.

shellsplit → array Показать исходный код
# File lib/shellwords.rb, line 227
def shellsplit
  Shellwords.split(self)
end

Разбивает str на массив токенов так же, как это делает оболочка UNIX Bourne.

Подробности см. в разделе Shellwords.shellsplit.

size
Псевдоним для: length
slice
Псевдоним для: []
slice!(index) → new_string or nil Показать исходный код
slice!(start, length) → new_string or nil
slice!(range) → new_string or nil
slice!(regexp, capture = 0) → new_string or nil
slice!(substring) → new_string or nil
static VALUE
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
{
    VALUE result = Qnil;
    VALUE indx;
    long beg, len = 1;
    char *p;

    rb_check_arity(argc, 1, 2);
    str_modify_keep_cr(str);
    indx = argv[0];
    if (RB_TYPE_P(indx, T_REGEXP)) {
        if (rb_reg_search(indx, str, 0, 0) < 0) return Qnil;
        VALUE match = rb_backref_get();
        struct re_registers *regs = RMATCH_REGS(match);
        int nth = 0;
        if (argc > 1 && (nth = rb_reg_backref_number(match, argv[1])) < 0) {
            if ((nth += regs->num_regs) <= 0) return Qnil;
        }
        else if (nth >= regs->num_regs) return Qnil;
        beg = BEG(nth);
        len = END(nth) - beg;
        goto subseq;
    }
    else if (argc == 2) {
        beg = NUM2LONG(indx);
        len = NUM2LONG(argv[1]);
        goto num_index;
    }
    else if (FIXNUM_P(indx)) {
        beg = FIX2LONG(indx);
        if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
        if (!len) return Qnil;
        beg = p - RSTRING_PTR(str);
        goto subseq;
    }
    else if (RB_TYPE_P(indx, T_STRING)) {
        beg = rb_str_index(str, indx, 0);
        if (beg == -1) return Qnil;
        len = RSTRING_LEN(indx);
        result = str_duplicate(rb_cString, indx);
        goto squash;
    }
    else {
        switch (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 0)) {
          case Qnil:
            return Qnil;
          case Qfalse:
            beg = NUM2LONG(indx);
            if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
            if (!len) return Qnil;
            beg = p - RSTRING_PTR(str);
            goto subseq;
          default:
            goto num_index;
        }
    }

  num_index:
    if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
    beg = p - RSTRING_PTR(str);

  subseq:
    result = rb_str_new(RSTRING_PTR(str)+beg, len);
    rb_enc_cr_str_copy_for_substr(result, str);

  squash:
    if (len > 0) {
        if (beg == 0) {
            rb_str_drop_bytes(str, len);
        }
        else {
            char *sptr = RSTRING_PTR(str);
            long slen = RSTRING_LEN(str);
            if (beg + len > slen) /* pathological check */
                len = slen - beg;
            memmove(sptr + beg,
                    sptr + beg + len,
                    slen - (beg + len));
            slen -= len;
            STR_SET_LEN(str, slen);
            TERM_FILL(&sptr[slen], TERM_LEN(str));
        }
    }
    return result;
}

Работает как String#[] (и его псевдоним String#slice), за исключением того, что:

  • Подстановки выполняются непосредственно в self (а не в копии self).

  • Если были внесены изменения, возвращает удалённую подстроку, а в противном случае — nil.

Несколько примеров:

s = 'hello'
s.slice!('e') # => "e"
s             # => "hllo"
s.slice!('e') # => nil
s             # => "hllo"

Связанные разделы: см. Изменение.

split(field_sep = $;, limit = 0) → array_of_substrings Показать исходный код
split(field_sep = $;, limit = 0) {|substring| ... } → self
static VALUE
rb_str_split_m(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    VALUE spat;
    VALUE limit;
    split_type_t split_type;
    long beg, end, i = 0, empty_count = -1;
    int lim = 0;
    VALUE result, tmp;

    result = rb_block_given_p() ? Qfalse : Qnil;
    if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
        lim = NUM2INT(limit);
        if (lim <= 0) limit = Qnil;
        else if (lim == 1) {
            if (RSTRING_LEN(str) == 0)
                return result ? rb_ary_new2(0) : str;
            tmp = str_duplicate(rb_cString, str);
            if (!result) {
                rb_yield(tmp);
                return str;
            }
            return rb_ary_new3(1, tmp);
        }
        i = 1;
    }
    if (NIL_P(limit) && !lim) empty_count = 0;

    enc = STR_ENC_GET(str);
    split_type = SPLIT_TYPE_REGEXP;
    if (!NIL_P(spat)) {
        spat = get_pat_quoted(spat, 0);
    }
    else if (NIL_P(spat = rb_fs)) {
        split_type = SPLIT_TYPE_AWK;
    }
    else if (!(spat = rb_fs_check(spat))) {
        rb_raise(rb_eTypeError, "value of $; must be String or Regexp");
    }
    else {
        rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$; is set to non-nil value");
    }
    if (split_type != SPLIT_TYPE_AWK) {
        switch (BUILTIN_TYPE(spat)) {
          case T_REGEXP:
            rb_reg_options(spat); /* check if uninitialized */
            tmp = RREGEXP_SRC(spat);
            split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
            if (split_type == SPLIT_TYPE_AWK) {
                spat = tmp;
                split_type = SPLIT_TYPE_STRING;
            }
            break;

          case T_STRING:
            mustnot_broken(spat);
            split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
            break;

          default:
            UNREACHABLE_RETURN(Qnil);
        }
    }

#define SPLIT_STR(beg, len) ( \
        empty_count = split_string(result, str, beg, len, empty_count), \
        str_mod_check(str, str_start, str_len))

    beg = 0;
    char *ptr = RSTRING_PTR(str);
    char *const str_start = ptr;
    const long str_len = RSTRING_LEN(str);
    char *const eptr = str_start + str_len;
    if (split_type == SPLIT_TYPE_AWK) {
        char *bptr = ptr;
        int skip = 1;
        unsigned int c;

        if (result) result = rb_ary_new();
        end = beg;
        if (is_ascii_string(str)) {
            while (ptr < eptr) {
                c = (unsigned char)*ptr++;
                if (skip) {
                    if (ascii_isspace(c)) {
                        beg = ptr - bptr;
                    }
                    else {
                        end = ptr - bptr;
                        skip = 0;
                        if (!NIL_P(limit) && lim <= i) break;
                    }
                }
                else if (ascii_isspace(c)) {
                    SPLIT_STR(beg, end-beg);
                    skip = 1;
                    beg = ptr - bptr;
                    if (!NIL_P(limit)) ++i;
                }
                else {
                    end = ptr - bptr;
                }
            }
        }
        else {
            while (ptr < eptr) {
                int n;

                c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
                ptr += n;
                if (skip) {
                    if (rb_isspace(c)) {
                        beg = ptr - bptr;
                    }
                    else {
                        end = ptr - bptr;
                        skip = 0;
                        if (!NIL_P(limit) && lim <= i) break;
                    }
                }
                else if (rb_isspace(c)) {
                    SPLIT_STR(beg, end-beg);
                    skip = 1;
                    beg = ptr - bptr;
                    if (!NIL_P(limit)) ++i;
                }
                else {
                    end = ptr - bptr;
                }
            }
        }
    }
    else if (split_type == SPLIT_TYPE_STRING) {
        char *substr_start = ptr;
        char *sptr = RSTRING_PTR(spat);
        long slen = RSTRING_LEN(spat);

        if (result) result = rb_ary_new();
        mustnot_broken(str);
        enc = rb_enc_check(str, spat);
        while (ptr < eptr &&
               (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
            /* Check we are at the start of a char */
            char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
            if (t != ptr + end) {
                ptr = t;
                continue;
            }
            SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
            str_mod_check(spat, sptr, slen);
            ptr += end + slen;
            substr_start = ptr;
            if (!NIL_P(limit) && lim <= ++i) break;
        }
        beg = ptr - str_start;
    }
    else if (split_type == SPLIT_TYPE_CHARS) {
        int n;

        if (result) result = rb_ary_new_capa(RSTRING_LEN(str));
        mustnot_broken(str);
        enc = rb_enc_get(str);
        while (ptr < eptr &&
               (n = rb_enc_precise_mbclen(ptr, eptr, enc)) > 0) {
            SPLIT_STR(ptr - str_start, n);
            ptr += n;
            if (!NIL_P(limit) && lim <= ++i) break;
        }
        beg = ptr - str_start;
    }
    else {
        if (result) result = rb_ary_new();
        long len = RSTRING_LEN(str);
        long start = beg;
        long idx;
        int last_null = 0;
        struct re_registers *regs;
        VALUE match = 0;

        for (; rb_reg_search(spat, str, start, 0) >= 0;
             (match ? (rb_match_unbusy(match), rb_backref_set(match)) : (void)0)) {
            match = rb_backref_get();
            if (!result) rb_match_busy(match);
            regs = RMATCH_REGS(match);
            end = BEG(0);
            if (start == end && BEG(0) == END(0)) {
                if (!ptr) {
                    SPLIT_STR(0, 0);
                    break;
                }
                else if (last_null == 1) {
                    SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, eptr, enc));
                    beg = start;
                }
                else {
                    if (start == len)
                        start++;
                    else
                        start += rb_enc_fast_mbclen(ptr+start,eptr,enc);
                    last_null = 1;
                    continue;
                }
            }
            else {
                SPLIT_STR(beg, end-beg);
                beg = start = END(0);
            }
            last_null = 0;

            for (idx=1; idx < regs->num_regs; idx++) {
                if (BEG(idx) == -1) continue;
                SPLIT_STR(BEG(idx), END(idx)-BEG(idx));
            }
            if (!NIL_P(limit) && lim <= ++i) break;
        }
        if (match) rb_match_unbusy(match);
    }
    if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
        SPLIT_STR(beg, RSTRING_LEN(str)-beg);
    }

    return result ? result : str;
}

Создаёт массив подстрок, разбивая self при каждом вхождении заданного разделителя полей field_sep.

Если аргументы не указаны, разделение выполняется с использованием разделителя полей $;, значение которого по умолчанию — nil.

Если блок не задан, возвращает массив подстрок:

'abracadabra'.split('a') # => ["", "br", "c", "d", "br"]

Если field_sep равен nil или ' ' (одному пробелу), разделение выполняется при каждой последовательности пробельных символов:

'foo bar baz'.split(nil)          # => ["foo", "bar", "baz"]
'foo bar baz'.split(' ')          # => ["foo", "bar", "baz"]
"foo \n\tbar\t\n  baz".split(' ') # => ["foo", "bar", "baz"]
'foo  bar   baz'.split(' ')       # => ["foo", "bar", "baz"]
''.split(' ')                     # => []

Если field_sep — пустая строка, разделение выполняется по каждому символу:

'abracadabra'.split('') # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
''.split('')            # => []
'тест'.split('')        # => ["т", "е", "с", "т"]
'こんにちは'.split('')   # => ["こ", "ん", "に", "ち", "は"]

Если field_sep — непустая строка, отличная от ' ' (одного пробела), эта строка используется как разделитель:

'abracadabra'.split('a')  # => ["", "br", "c", "d", "br"]
'abracadabra'.split('ab') # => ["", "racad", "ra"]
''.split('a')             # => []
'тест'.split('т')         # => ["", "ес"]
'こんにちは'.split('に')    # => ["こん", "ちは"]

Если field_sep — это Regexp, разделение выполняется при каждом вхождении соответствующей подстроки:

'abracadabra'.split(/ab/) # => ["", "racad", "ra"]
'1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"]
'abracadabra'.split(//)   # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]

Если регулярное выражение содержит группы, соответствующие им значения включаются в возвращаемый массив:

'1:2:3'.split(/(:)()()/, 2) # => ["1", ":", "", "", "2:3"]

Аргумент limit задаёт ограничение на размер возвращаемого массива; он также определяет, будут ли завершающие пустые строки включены в возвращаемый массив.

Если limit равен нулю, размер массива не ограничен, но завершающие пустые строки опускаются:

'abracadabra'.split('', 0)  # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
'abracadabra'.split('a', 0) # => ["", "br", "c", "d", "br"]  # Empty string after last 'a' omitted.

Если limit — положительное целое число, размер массива ограничен (будет выполнено не более n - 1 разделений), а завершающие пустые строки включаются:

'abracadabra'.split('', 3)   # => ["a", "b", "racadabra"]
'abracadabra'.split('a', 3)  # => ["", "br", "cadabra"]
'abracadabra'.split('', 30)  # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a", ""]
'abracadabra'.split('a', 30) # => ["", "br", "c", "d", "br", ""]
'abracadabra'.split('', 1)   # => ["abracadabra"]
'abracadabra'.split('a', 1)  # => ["abracadabra"]

Если limit отрицателен, размер массива не ограничен, а завершающие пустые строки опускаются:

'abracadabra'.split('', -1)  # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a", ""]
'abracadabra'.split('a', -1) # => ["", "br", "c", "d", "br", ""]

Если задан блок, он вызывается для каждой подстроки и возвращает self:

'foo bar baz'.split(' ') {|substring| p substring }

Вывод:

"foo"
"bar"
"baz"

Обратите внимание, что приведённый выше пример функционально эквивалентен следующему:

'foo bar baz'.split(' ').each {|substring| p substring }

Вывод:

"foo"
"bar"
"baz"

Однако последний вариант:

  • Работает медленнее, поскольку создаёт промежуточный массив.

  • Возвращает массив (вместо self).

Связанные разделы: см. Преобразование в нестроку.

squeeze(*selectors) → new_string Показать исходный код
static VALUE
rb_str_squeeze(int argc, VALUE *argv, VALUE str)
{
    str = str_duplicate(rb_cString, str);
    rb_str_squeeze_bang(argc, argv, str);
    return str;
}

Возвращает копию self, в которой каждая последовательность (удвоение, утроение и т. д.) указанных символов «сжата» до одного символа.

Последовательности для сжатия задаются аргументами selectors, каждый из которых является строкой; см. Селекторы символов.

Один аргумент может быть одним символом:

'Noooooo!'.squeeze('o')      # => "No!"
'foo  bar  baz'.squeeze(' ') # => "foo bar baz"
'Mississippi'.squeeze('s')   # => "Misisippi"
'Mississippi'.squeeze('p')   # => "Mississipi"
'Mississippi'.squeeze('x')   # => "Mississippi"  # Unused selector character is ignored.
'бессонница'.squeeze('с')    # => "бесонница"
'бессонница'.squeeze('н')    # => "бессоница"

Один аргумент может быть строкой символов:

'Mississippi'.squeeze('sp')       # => "Misisipi"
'Mississippi'.squeeze('ps')       # => "Misisipi"   # Order doesn't matter.
'Mississippi'.squeeze('nonsense') # => "Misisippi"  # Unused selector characters are ignored.

Один аргумент может быть диапазоном символов:

'Mississippi'.squeeze('a-p') # => "Mississipi"
'Mississippi'.squeeze('q-z') # => "Misisippi"
'Mississippi'.squeeze('a-z') # => "Misisipi"

Допускается несколько аргументов; см. Несколько селекторов символов.

Связанные разделы: см. Преобразование в новую строку.

squeeze!(*selectors) → self or nil Показать исходный код
static VALUE
rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
{
    char squeez[TR_TABLE_SIZE];
    rb_encoding *enc = 0;
    VALUE del = 0, nodel = 0;
    unsigned char *s, *send, *t;
    int i, modify = 0;
    int ascompat, singlebyte = single_byte_optimizable(str);
    unsigned int save;

    if (argc == 0) {
        enc = STR_ENC_GET(str);
    }
    else {
        for (i=0; i<argc; i++) {
            VALUE s = argv[i];

            StringValue(s);
            enc = rb_enc_check(str, s);
            if (singlebyte && !single_byte_optimizable(s))
                singlebyte = 0;
            tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
        }
    }

    str_modify_keep_cr(str);
    s = t = (unsigned char *)RSTRING_PTR(str);
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
    send = (unsigned char *)RSTRING_END(str);
    save = -1;
    ascompat = rb_enc_asciicompat(enc);

    if (singlebyte) {
        while (s < send) {
            unsigned int c = *s++;
            if (c != save || (argc > 0 && !squeez[c])) {
                *t++ = save = c;
            }
        }
    }
    else {
        while (s < send) {
            unsigned int c;
            int clen;

            if (ascompat && (c = *s) < 0x80) {
                if (c != save || (argc > 0 && !squeez[c])) {
                    *t++ = save = c;
                }
                s++;
            }
            else {
                c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, enc);

                if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
                    if (t != s) rb_enc_mbcput(c, t, enc);
                    save = c;
                    t += clen;
                }
                s += clen;
            }
        }
    }

    TERM_FILL((char *)t, TERM_LEN(str));
    if ((char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
        STR_SET_LEN(str, (char *)t - RSTRING_PTR(str));
        modify = 1;
    }

    if (modify) return str;
    return Qnil;
}

Как String#squeeze, но:

  • Символы сжимаются в self (а не в копии self).

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные разделы: см. Изменение.

start_with?(*patterns) → true or false Показать исходный код
static VALUE
rb_str_start_with(int argc, VALUE *argv, VALUE str)
{
    int i;

    for (i=0; i<argc; i++) {
        VALUE tmp = argv[i];
        if (RB_TYPE_P(tmp, T_REGEXP)) {
            if (rb_reg_start_with_p(tmp, str))
                return Qtrue;
        }
        else {
            const char *p, *s, *e;
            long slen, tlen;
            rb_encoding *enc;

            StringValue(tmp);
            enc = rb_enc_check(str, tmp);
            if ((tlen = RSTRING_LEN(tmp)) == 0) return Qtrue;
            if ((slen = RSTRING_LEN(str)) < tlen) continue;
            p = RSTRING_PTR(str);
            e = p + slen;
            s = p + tlen;
            if (!at_char_right_boundary(p, s, e, enc))
                continue;
            if (memcmp(p, RSTRING_PTR(tmp), tlen) == 0)
                return Qtrue;
        }
    }
    return Qfalse;
}

Возвращает значение, указывающее, начинается ли self с любого из заданных patterns.

Для каждого аргумента используется следующий шаблон:

  • Сам шаблон, если это Regexp.

  • Regexp.quote(pattern), если это строка.

Возвращает true, если какой-либо шаблон соответствует началу строки, и false в противном случае:

'hello'.start_with?('hell')               # => true
'hello'.start_with?(/H/i)                 # => true
'hello'.start_with?('heaven', 'hell')     # => true
'hello'.start_with?('heaven', 'paradise') # => false
'тест'.start_with?('т')                   # => true
'こんにちは'.start_with?('こ')              # => true

Связанные разделы: см. Проверка.

strip(*selectors) → new_string Показать исходный код
static VALUE
rb_str_strip(int argc, VALUE *argv, VALUE str)
{
    char *start;
    long olen, loffset, roffset;
    rb_encoding *enc = STR_ENC_GET(str);

    RSTRING_GETMEM(str, start, olen);

    if (argc > 0) {
        char table[TR_TABLE_SIZE];
        VALUE del = 0, nodel = 0;

        tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
        loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
        roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
    }
    else {
        loffset = lstrip_offset(str, start, start+olen, enc);
        roffset = rstrip_offset(str, start+loffset, start+olen, enc);
    }

    if (loffset <= 0 && roffset <= 0) return str_duplicate(rb_cString, str);
    return rb_str_subseq(str, loffset, olen-loffset-roffset);
}

Возвращает копию self без пробельных символов в начале и конце; см. Пробельные символы в строках:

whitespace = "\x00\t\n\v\f\r "
s = whitespace + 'abc' + whitespace
# => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
s.strip # => "abc"

Если заданы selectors, удаляет символы из selectors с обоих концов self:

s = "---abc+++"
s.strip("-+") # => "abc"
s.strip("+-") # => "abc"

selectors должны быть допустимыми селекторами символов (см. Селекторы символов); можно использовать любую допустимую форму, в том числе отрицание, диапазоны и escape-последовательности:

"01234abc56789".strip("0-9") # "abc"
"01234abc56789".strip("0-9", "^4-6") # "4abc56"

Связанные разделы: см. Преобразование в новую строку.

strip!(*selectors) → self or nil Показать исходный код
static VALUE
rb_str_strip_bang(int argc, VALUE *argv, 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);

    if (argc > 0) {
        char table[TR_TABLE_SIZE];
        VALUE del = 0, nodel = 0;

        tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
        loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
        roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
    }
    else {
        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);
        TERM_FILL(start+len, rb_enc_mbminlen(enc));
        return str;
    }
    return Qnil;
}

Как String#strip, но:

  • Все изменения вносятся в self.

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные разделы: см. Изменение.

sub(pattern, replacement) → new_string Показать исходный код
sub(pattern) {|match| ... } → new_string
static VALUE
rb_str_sub(int argc, VALUE *argv, VALUE str)
{
    str = str_duplicate(rb_cString, str);
    rb_str_sub_bang(argc, argv, str);
    return str;
}

Возвращает копию self, возможно, с заменённой подстрокой.

Аргумент pattern может быть строкой или Regexp; аргумент replacement может быть строкой или Hash.

Разнообразие типов значений аргументов делает этот метод весьма универсальным.

Ниже приведены несколько простых примеров; дополнительные примеры см. в разделе Методы подстановки.

Если заданы аргументы pattern и строка replacement, первая совпавшая подстрока заменяется указанной строкой замены:

s = 'abracadabra'       # => "abracadabra"
s.sub('bra', 'xyzzy')   # => "axyzzycadabra"
s.sub(/bra/, 'xyzzy')   # => "axyzzycadabra"
s.sub('nope', 'xyzzy')  # => "abracadabra"

Если заданы аргументы pattern и хеш replacement, первая совпавшая подстрока заменяется значением из указанного хеша замен или удаляется:

h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
s.sub('b', h)  # => "aBracadabra"
s.sub(/b/, h)  # => "aBracadabra"
s.sub(/d/, h)  # => "abracaabra"  # 'd' removed.

Если задан аргумент pattern и блок, блок вызывается для каждой совпавшей подстроки; эта подстрока заменяется возвращаемым блоком значением:

s.sub('b') {|match| match.upcase } # => "aBracadabra"

Связанные разделы: см. Преобразование в новую строку.

sub!(pattern, replacement) → self or nil Показать исходный код
sub!(pattern) {|match| ... } → self or nil
static VALUE
rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
{
    VALUE pat, repl, hash = Qnil;
    int iter = 0;
    long plen;
    int min_arity = rb_block_given_p() ? 1 : 2;
    long beg;

    rb_check_arity(argc, min_arity, 2);
    if (argc == 1) {
        iter = 1;
    }
    else {
        repl = argv[1];
        hash = rb_check_hash_type(argv[1]);
        if (NIL_P(hash)) {
            StringValue(repl);
        }
    }

    pat = get_pat_quoted(argv[0], 1);

    str_modifiable(str);
    beg = rb_pat_search(pat, str, 0, 1);
    if (beg >= 0) {
        rb_encoding *enc;
        int cr = ENC_CODERANGE(str);
        long beg0, end0;
        VALUE match, match0 = Qnil;
        struct re_registers *regs;
        char *p, *rp;
        long len, rlen;

        match = rb_backref_get();
        regs = RMATCH_REGS(match);
        if (RB_TYPE_P(pat, T_STRING)) {
            beg0 = beg;
            end0 = beg0 + RSTRING_LEN(pat);
            match0 = pat;
        }
        else {
            beg0 = BEG(0);
            end0 = END(0);
            if (iter) match0 = rb_reg_nth_match(0, match);
        }

        if (iter || !NIL_P(hash)) {
            p = RSTRING_PTR(str); len = RSTRING_LEN(str);

            if (iter) {
                repl = rb_obj_as_string(rb_yield(match0));
            }
            else {
                repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
                repl = rb_obj_as_string(repl);
            }
            str_mod_check(str, p, len);
            rb_check_frozen(str);
        }
        else {
            repl = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
        }

        enc = rb_enc_compatible(str, repl);
        if (!enc) {
            rb_encoding *str_enc = STR_ENC_GET(str);
            p = RSTRING_PTR(str); len = RSTRING_LEN(str);
            if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
                coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
                rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
                         rb_enc_inspect_name(str_enc),
                         rb_enc_inspect_name(STR_ENC_GET(repl)));
            }
            enc = STR_ENC_GET(repl);
        }
        rb_str_modify(str);
        rb_enc_associate(str, enc);
        if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
            int cr2 = ENC_CODERANGE(repl);
            if (cr2 == ENC_CODERANGE_BROKEN ||
                (cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
                cr = ENC_CODERANGE_UNKNOWN;
            else
                cr = cr2;
        }
        plen = end0 - beg0;
        rlen = RSTRING_LEN(repl);
        len = RSTRING_LEN(str);
        if (rlen > plen) {
            RESIZE_CAPA(str, len + rlen - plen);
        }
        p = RSTRING_PTR(str);
        if (rlen != plen) {
            memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
        }
        rp = RSTRING_PTR(repl);
        memmove(p + beg0, rp, rlen);
        len += rlen - plen;
        STR_SET_LEN(str, len);
        TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
        ENC_CODERANGE_SET(str, cr);

        RB_GC_GUARD(match);

        return str;
    }
    return Qnil;
}

Как String#sub, но:

  • Изменения вносятся в self, а не в копию self.

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные разделы: см. Изменение.

succ → new_str Показать исходный код
VALUE
rb_str_succ(VALUE orig)
{
    VALUE str;
    str = rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
    rb_enc_cr_str_copy_for_substr(str, orig);
    return str_succ(str);
}

Возвращает следующее значение после self. Следующее значение вычисляется путём увеличения символов.

Первым увеличивается крайний справа буквенно-цифровой символ; если таких символов нет — крайний справа символ:

'THX1138'.succ   # => "THX1139"
'<<koala>>'.succ # => "<<koalb>>"
'***'.succ       # => '**+'
'тест'.succ      # => "тесу"
'こんにちは'.succ  # => "こんにちば"

Следующим символом после цифры является другая цифра; при переходе от 9 к 0 выполняется перенос на следующий символ слева, а при необходимости добавляется ещё одна цифра в начало:

'00'.succ # => "01"
'09'.succ # => "10"
'99'.succ # => "100"

Следующим символом после буквы является другая буква того же регистра; при переходе выполняется перенос на следующий символ слева, а при необходимости в начало добавляется ещё одна буква того же регистра:

'aa'.succ # => "ab"
'az'.succ # => "ba"
'zz'.succ # => "aaa"
'AA'.succ # => "AB"
'AZ'.succ # => "BA"
'ZZ'.succ # => "AAA"

Следующим символом после небуквенно-цифрового символа является следующий символ в последовательности сортировки используемого набора символов; при переходе выполняется перенос на следующий символ слева, а при необходимости добавляется ещё один символ:

s = 0.chr * 3   # => "\x00\x00\x00"
s.succ        # => "\x00\x00\x01"
s = 255.chr * 3 # => "\xFF\xFF\xFF"
s.succ        # => "\x01\x00\x00\x00"

Перенос может происходить между буквенно-цифровыми символами разных типов и внутри их последовательностей:

s = 'zz99zz99' # => "zz99zz99"
s.succ         # => "aaa00aa00"
s = '99zz99zz' # => "99zz99zz"
s.succ         # => "100aa00aa"

Следующее значение после пустой String — новая пустая String:

''.succ # => ""

Связанные разделы: см. Преобразование в новую строку.

Также имеет псевдоним: next
succ! → self Показать исходный код
static VALUE
rb_str_succ_bang(VALUE str)
{
    rb_str_modify(str);
    str_succ(str);
    return str;
}

Как String#succ, но изменяет self на месте и возвращает self.

Связанные разделы: см. Изменение.

Также имеет псевдоним: next!
sum(n = 16) → integer Показать исходный код
static VALUE
rb_str_sum(int argc, VALUE *argv, VALUE str)
{
    int bits = 16;
    char *ptr, *p, *pend;
    long len;
    VALUE sum = INT2FIX(0);
    unsigned long sum0 = 0;

    if (rb_check_arity(argc, 0, 1) && (bits = NUM2INT(argv[0])) < 0) {
        bits = 0;
    }
    ptr = p = RSTRING_PTR(str);
    len = RSTRING_LEN(str);
    pend = p + len;

    while (p < pend) {
        if (FIXNUM_MAX - UCHAR_MAX < sum0) {
            sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
            str_mod_check(str, ptr, len);
            sum0 = 0;
        }
        sum0 += (unsigned char)*p;
        p++;
    }

    if (bits == 0) {
        if (sum0) {
            sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
        }
    }
    else {
        if (sum == INT2FIX(0)) {
            if (bits < (int)sizeof(long)*CHAR_BIT) {
                sum0 &= (((unsigned long)1)<<bits)-1;
            }
            sum = LONG2FIX(sum0);
        }
        else {
            VALUE mod;

            if (sum0) {
                sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
            }

            mod = rb_funcall(INT2FIX(1), idLTLT, 1, INT2FIX(bits));
            mod = rb_funcall(mod, '-', 1, INT2FIX(1));
            sum = rb_funcall(sum, '&', 1, mod);
        }
    }
    return sum;
}

Возвращает простую n-битную контрольную сумму символов в self; контрольная сумма представляет собой сумму двоичных значений каждого байта в self по модулю 2**n - 1:

'hello'.sum     # => 532
'hello'.sum(4)  # => 4
'hello'.sum(64) # => 532
'тест'.sum      # => 1405
'こんにちは'.sum  # => 2582

Это не особенно надёжная контрольная сумма.

Связанные разделы: см. Проверка.

swapcase(mapping = :ascii) → new_string Показать исходный код
static VALUE
rb_str_swapcase(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
    VALUE ret;

    flags = check_case_options(argc, argv, flags);
    enc = str_true_enc(str);
    if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str_duplicate(rb_cString, str);
    if (flags&ONIGENC_CASE_ASCII_ONLY) {
        ret = rb_str_new(0, RSTRING_LEN(str));
        rb_str_ascii_casemap(str, ret, &flags, enc);
    }
    else {
        ret = rb_str_casemap(str, &flags, enc);
    }
    return ret;
}

Возвращает строку, содержащую символы из self, с обратным регистром:

  • Каждый символ в верхнем регистре переводится в нижний.

  • Каждый символ в нижнем регистре переводится в верхний.

Примеры:

'Hello'.swapcase        # => "hELLO"
'Straße'.swapcase       # => "sTRASSE"
'Привет'.swapcase       # => "пРИВЕТ"
'RubyGems.org'.swapcase # => "rUBYgEMS.ORG"

Размеры self и результата преобразования в верхний регистр могут различаться:

s = 'Straße'
s.size          # => 6
s.swapcase      # => "sTRASSE"
s.swapcase.size # => 7

У некоторых символов (и некоторых наборов символов) нет вариантов в верхнем и нижнем регистре; см. Преобразование регистра:

s = '1, 2, 3, ...'
s.swapcase == s # => true
s = 'こんにちは'
s.swapcase == s # => true

Регистр зависит от заданного mapping, которым может быть :ascii, :fold или :turkic; см. Преобразования регистра.

Связанные методы: см. Преобразование в новую строку.

swapcase!(mapping) → self or nil Показать исходный код
static VALUE
rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;

    flags = check_case_options(argc, argv, flags);
    str_modify_keep_cr(str);
    enc = str_true_enc(str);
    if (flags&ONIGENC_CASE_ASCII_ONLY)
        rb_str_ascii_casemap(str, str, &flags, enc);
    else
        str_shared_replace(str, rb_str_casemap(str, &flags, enc));

    if (ONIGENC_CASE_MODIFIED&flags) return str;
    return Qnil;
}

Как String#swapcase, но:

  • Изменения вносятся в self, а не в копию self.

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные методы: см. Изменение.

to_c → complex Показать исходный код
static VALUE
string_to_c(VALUE self)
{
    VALUE num;

    rb_must_asciicompat(self);

    (void)parse_comp(rb_str_fill_terminator(self, 1), FALSE, &num);

    return num;
}

Возвращает объект Complex: разбирает начальную подстроку self, извлекая два числовых значения, которые становятся координатами комплексного объекта.

Подстрока интерпретируется как содержащая либо прямоугольные координаты (действительную и мнимую части), либо полярные координаты (модуль и угол) — в зависимости от наличия явного или подразумеваемого символа-разделителя:

  • '+', '-' или отсутствие разделителя: прямоугольные координаты.

  • '@': полярные координаты.

Кратко

В этих примерах мы используем метод Complex#rect для отображения прямоугольных координат, а метод Complex#polar — для отображения полярных координат.

# Rectangular coordinates.

# Real-only: no separator; imaginary part is zero.
'9'.to_c.rect         # => [9, 0]         # Integer.
'-9'.to_c.rect        # => [-9, 0]        # Integer (negative).
'2.5'.to_c.rect       # => [2.5, 0]       # Float.
'1.23e-14'.to_c.rect  # => [1.23e-14, 0]  # Float with exponent.
'2.5/1'.to_c.rect     # => [(5/2), 0]     # Rational.

# Some things are ignored.
'foo1'.to_c.rect      # => [0, 0]         # Unparsed entire substring.
'1foo'.to_c.rect      # => [1, 0]         # Unparsed trailing substring.
' 1 '.to_c.rect       # => [1, 0]         # Leading and trailing whitespace.
*
# Imaginary only: trailing 'i' required; real part is zero.
'9i'.to_c.rect        # => [0, 9]
'-9i'.to_c.rect       # => [0, -9]
'2.5i'.to_c.rect      # => [0, 2.5]
'1.23e-14i'.to_c.rect # => [0, 1.23e-14]
'2.5/1i'.to_c.rect    # => [0, (5/2)]

# Real and imaginary; '+' or '-' separator; trailing 'i' required.
'2+3i'.to_c.rect      # => [2, 3]
'-2-3i'.to_c.rect     # => [-2, -3]
'2.5+3i'.to_c.rect    # => [2.5, 3]
'2.5+3/2i'.to_c.rect  # => [2.5, (3/2)]

# Polar coordinates; '@' separator; magnitude required.
'1.0@0'.to_c.polar             # => [1.0, 0.0]
'1.0@'.to_c.polar              # => [1.0, 0.0]
"1.0@#{Math::PI}".to_c.polar   # => [1.0, 3.141592653589793]
"1.0@#{Math::PI/2}".to_c.polar # => [1.0, 1.5707963267948966]

Разбираемые значения

Разбор можно представить как поиск числовых литералов, встроенных в подстроку.

В этом разделе показано, как метод разбирает числовые значения из начальных подстрок. В примерах разбирается только действительная или только мнимая часть; для каждой части разбор выполняется одинаково.

'1foo'.to_c # => (1+0i)      # Ignores trailing unparsed characters.
' 1 '.to_c  # => (1+0i)      # Ignores leading and trailing whitespace.
'x1'.to_c   # => (0+0i)      # Finds no leading numeric.

# Integer literal embedded in the substring.
'1'.to_c       # => (1+0i)
'-1'.to_c      # => (-1+0i)
'1i'.to_c      # => (0+1i)

# Integer literals that don't work.
'0b100'.to_c   # => (0+0i)   # Not parsed as binary.
'0o100'.to_c   # => (0+0i)   # Not parsed as octal.
'0d100'.to_c   # => (0+0i)   # Not parsed as decimal.
'0x100'.to_c   # => (0+0i)   # Not parsed as hexadecimal.
'010'.to_c     # => (10+0i)  # Not parsed as octal.

# Float literals:
'3.14'.to_c    # => (3.14+0i)
'3.14i'.to_c   # => (0+3.14i)
'1.23e4'.to_c  # => (12300.0+0i)
'1.23e+4'.to_c # => (12300.0+0i)
'1.23e-4'.to_c # => (0.000123+0i)

# Rational literals:
'1/2'.to_c     # => ((1/2)+0i)
'-1/2'.to_c    # => ((-1/2)+0i)
'1/2r'.to_c    # => ((1/2)+0i)
'-1/2r'.to_c   # => ((-1/2)+0i)

Прямоугольные координаты

При разделителе '+' или '-' либо при отсутствии разделителя значения интерпретируются как прямоугольные координаты: действительная и мнимая части.

При отсутствии разделителя единственное значение присваивается действительной или мнимой части:

 ''.to_c  # => (0+0i)  # Defaults to zero.
'1'.to_c  # => (1+0i)  # Real (no trailing 'i').
'1i'.to_c # => (0+1i)  # Imaginary (trailing 'i').
'i'.to_c  # => (0+1i)  # Special case (imaginary 1).

При разделителе '+' обе части положительны (или равны нулю):

# Without trailing 'i'.
'+'.to_c    # => (0+0i)  # No values: defaults to zero.
'+1'.to_c   # => (1+0i)  # Value after '+': real only.
'1+'.to_c   # => (1+0i)  # Value before '+': real only.
'2+1'.to_c  # => (2+0i)  # Values before and after '+': real and imaginary.
# With trailing 'i'.
'+1i'.to_c  # => (0+1i)  # Value after '+': imaginary only.
'2+i'.to_c  # => (2+1i)  # Value before '+': real and imaginary 1.
'2+1i'.to_c # => (2+1i)  # Values before and after '+': real and imaginary.

При разделителе '-' мнимая часть отрицательна:

# Without trailing 'i'.
'-'.to_c    # => (0+0i)   # No values: defaults to zero.
'-1'.to_c   # => (-1+0i)  # Value after '-': negative real, zero imaginary.
'1-'.to_c   # => (1+0i)   # Value before '-': positive real, zero imaginary.
'2-1'.to_c  # => (2+0i)   # Values before and after '-': positive real, zero imaginary.
# With trailing 'i'.
'-1i'.to_c  # => (0-1i)   # Value after '-': negative real, zero imaginary.
'2-i'.to_c  # => (2-1i)   # Value before '-': positive real, negative imaginary.
'2-1i'.to_c # => (2-1i)   # Values before and after '-': positive real, negative imaginary.

Обратите внимание: вместо символа в конце 'i' можно использовать один из символов 'I', 'j' или 'J' — результат будет тем же.

Полярные координаты

При разделителе '@') значения интерпретируются как полярные координаты: модуль и угол.

'2@'.to_c.polar  # => [2, 0.0]    # Value before '@': magnitude only.
 # Values before and after '@': magnitude and angle.
'2@1'.to_c.polar # => [2.0, 1.0]
"1.0@#{Math::PI/2}".to_c # => (0.0+1i)
"1.0@#{Math::PI}".to_c   # => (-1+0.0i)
# Magnitude not given: defaults to zero.
'@'.to_c.polar   # => [0, 0.0]
'@1'.to_c.polar  # => [0, 0.0]

'1.0@0'.to_c             # => (1+0.0i)

Обратите внимание: во всех случаях вместо символа в конце 'i' можно использовать один из символов 'I', 'j', 'J' — результат будет тем же.

См. Преобразование в объект, не являющийся строкой.

to_f → float Показать исходный код
static VALUE
rb_str_to_f(VALUE str)
{
    return DBL2NUM(rb_str_to_dbl(str, FALSE));
}
Returns the result of interpreting leading characters in +self+ as a Float:

  '3.14159'.to_f  # => 3.14159
  '1.234e-2'.to_f # => 0.01234

Characters past a leading valid number are ignored:

  '3.14 (pi to two places)'.to_f # => 3.14

Returns zero if there is no leading valid number:

  'abcdef'.to_f # => 0.0

См. Преобразование в объект, не являющийся строкой.

to_i(base = 10) → integer Показать исходный код
static VALUE
rb_str_to_i(int argc, VALUE *argv, VALUE str)
{
    int base = 10;

    if (rb_check_arity(argc, 0, 1) && (base = NUM2INT(argv[0])) < 0) {
        rb_raise(rb_eArgError, "invalid radix %d", base);
    }
    return rb_str_to_inum(str, base, FALSE);
}

Возвращает результат интерпретации начальных символов self как целого числа в заданной системе счисления base; base должно быть равно 0 или находиться в диапазоне (2..36):

'123456'.to_i     # => 123456
'123def'.to_i(16) # => 1195503

Если задано base, строка object может содержать начальные символы, указывающие фактическую систему счисления:

'123def'.to_i(0)   # => 123
'0123def'.to_i(0)  # => 83
'0b123def'.to_i(0) # => 1
'0o123def'.to_i(0) # => 83
'0d123def'.to_i(0) # => 123
'0x123def'.to_i(0) # => 1195503

Символы после начального корректного числа (в заданной системе счисления base) игнорируются:

'12.345'.to_i   # => 12
'12345'.to_i(2) # => 1

Возвращает ноль, если начальное корректное число отсутствует:

'abcdef'.to_i # => 0
'2'.to_i(2)   # => 0

Связанные методы: см. Преобразование в объект, не являющийся строкой.

to_json_raw(*args) Показать исходный код
# File ext/json/lib/json/add/string.rb, line 32
def to_json_raw(...)
  to_json_raw_object.to_json(...)
end

Этот метод создает текст JSON на основе результата вызова to_json_raw_object для этого объекта String.

to_json_raw_object() Показать исходный код
# File ext/json/lib/json/add/string.rb, line 21
def to_json_raw_object
  {
    JSON.create_id => self.class.name,
    "raw" => unpack("C*"),
  }
end

Этот метод создает необработанный хеш-объект, который можно включать в другие структуры данных и который будет сгенерирован как необработанная строка. Этот метод следует использовать, если требуется преобразовать необработанные строки в JSON, а не в строки UTF-8, например для двоичных данных.

to_r → rational Показать исходный код
static VALUE
string_to_r(VALUE self)
{
    VALUE num;

    rb_must_asciicompat(self);

    num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);

    if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
        rb_raise(rb_eFloatDomainError, "Infinity");
    return num;
}

Возвращает результат интерпретации начальных символов self как рационального числа:

'123'.to_r       # => (123/1)   # Integer literal.
'300/2'.to_r     # => (150/1)   # Rational literal.
'-9.2'.to_r      # => (-46/5)   # Float literal.
'-9.2e2'.to_r    # => (-920/1)  # Float literal.

Игнорирует начальные и конечные пробелы, а также завершающие нечисловые символы:

' 2 '.to_r       # => (2/1)
'21-Jun-09'.to_r # => (21/1)

Возвращает рациональный ноль, если начальные числовые символы отсутствуют.

'BWV 1079'.to_r  # => (0/1)

ПРИМЕЧАНИЕ: '0.3'.to_r эквивалентно 3/10r, но отличается от 0.3.to_r:

'0.3'.to_r # => (3/10)
3/10r      # => (3/10)
0.3.to_r   # => (5404319552844595/18014398509481984)

Связанные методы: см. Преобразование в объект, не являющийся строкой.

to_s → self or new_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, если self является String, или self, преобразованный в String, если self является подклассом String.

Связанные методы: см. Преобразование в новую строку.

Также имеет псевдоним: to_str
to_str
Псевдоним для: to_s
to_sym
Псевдоним для: intern
tr(selector, replacements) → new_string Показать исходный код
static VALUE
rb_str_tr(VALUE str, VALUE src, VALUE repl)
{
    str = str_duplicate(rb_cString, str);
    tr_trans(str, src, repl, 0);
    return str;
}

Возвращает копию self, заменяя каждый символ, указанный в строке selector, соответствующим символом в строке replacements. Соответствие определяется позицией:

  • Каждое вхождение первого символа, указанного в selector, заменяется первым символом в replacements.

  • Каждое вхождение второго символа, указанного в selector, заменяется вторым символом в replacements.

  • И так далее.

Пример:

'hello'.tr('el', 'ip') #=> "hippo"

Если replacements короче, чем selector, он неявно дополняется своим последним символом:

'hello'.tr('aeiou', '-')   # => "h-ll-"
'hello'.tr('aeiou', 'AA-') # => "hAll-"

Аргументы selector и replacements должны быть допустимыми селекторами символов (см. Селекторы символов) и могут использовать любые допустимые формы, включая отрицание, диапазоны и escape-последовательности:

'hello'.tr('^aeiou', '-')       # => "-e--o"     # Negation.
'ibm'.tr('b-z', 'a-z')          # => "hal"       # Range.
'hel^lo'.tr('\^aeiou', '-')     # => "h-l-l-"    # Escaped leading caret.
'i-b-m'.tr('b\-z', 'a-z')       # => "ibabm"     # Escaped embedded hyphen.
'foo\\bar'.tr('ab\\', 'XYZ')    # => "fooZYXr"   # Escaped backslash.

Связанные методы: см. Преобразование в новую строку.

tr!(selector, replacements) → self or nil Показать исходный код
static VALUE
rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
{
    return tr_trans(str, src, repl, 0);
}

Как String#tr, но:

  • Выполняет замены в self (а не в копии self).

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные методы: Изменение.

tr_s(selector, replacements) → new_string Показать исходный код
static VALUE
rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
{
    str = str_duplicate(rb_cString, str);
    tr_trans(str, src, repl, 1);
    return str;
}

Как String#tr, но:

  • Также удаляет повторяющиеся символы в измененных частях преобразованной строки; см. String#squeeze.

  • Возвращает преобразованную строку с удаленными повторяющимися символами.

Примеры:

'hello'.tr_s('l', 'r')   #=> "hero"
'hello'.tr_s('el', '-')  #=> "h-o"
'hello'.tr_s('el', 'hx') #=> "hhxo"

Связанные методы: см. Преобразование в новую строку.

tr_s!(selector, replacements) → self or nil Показать исходный код
static VALUE
rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
{
    return tr_trans(str, src, repl, 1);
}

Как String#tr_s, но:

  • Изменяет self на месте (а не его копию self).

  • Возвращает self, если были внесены изменения, и nil в противном случае.

Связанные методы: Изменение.

undump → new_string Показать исходный код
static VALUE
str_undump(VALUE str)
{
    const char *s = RSTRING_PTR(str);
    const char *s_end = RSTRING_END(str);
    rb_encoding *enc = rb_enc_get(str);
    VALUE undumped = rb_enc_str_new(s, 0L, enc);
    bool utf8 = false;
    bool binary = false;
    int w;

    rb_must_asciicompat(str);
    if (rb_str_is_ascii_only_p(str) == Qfalse) {
        rb_raise(rb_eRuntimeError, "non-ASCII character detected");
    }
    if (!str_null_check(str, &w)) {
        rb_raise(rb_eRuntimeError, "string contains null byte");
    }
    if (RSTRING_LEN(str) < 2) goto invalid_format;
    if (*s != '"') goto invalid_format;

    /* strip '"' at the start */
    s++;

    for (;;) {
        if (s >= s_end) {
            rb_raise(rb_eRuntimeError, "unterminated dumped string");
        }

        if (*s == '"') {
            /* epilogue */
            s++;
            if (s == s_end) {
                /* ascii compatible dumped string */
                break;
            }
            else {
                static const char force_encoding_suffix[] = ".force_encoding(\""; /* "\")" */
                static const char dup_suffix[] = ".dup";
                const char *encname;
                int encidx;
                ptrdiff_t size;

                /* check separately for strings dumped by older versions */
                size = sizeof(dup_suffix) - 1;
                if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;

                size = sizeof(force_encoding_suffix) - 1;
                if (s_end - s <= size) goto invalid_format;
                if (memcmp(s, force_encoding_suffix, size) != 0) goto invalid_format;
                s += size;

                if (utf8) {
                    rb_raise(rb_eRuntimeError, "dumped string contained Unicode escape but used force_encoding");
                }

                encname = s;
                s = memchr(s, '"', s_end-s);
                size = s - encname;
                if (!s) goto invalid_format;
                if (s_end - s != 2) goto invalid_format;
                if (s[0] != '"' || s[1] != ')') goto invalid_format;

                encidx = rb_enc_find_index2(encname, (long)size);
                if (encidx < 0) {
                    rb_raise(rb_eRuntimeError, "dumped string has unknown encoding name");
                }
                rb_enc_associate_index(undumped, encidx);
            }
            break;
        }

        if (*s == '\\') {
            s++;
            if (s >= s_end) {
                rb_raise(rb_eRuntimeError, "invalid escape");
            }
            undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
        }
        else {
            rb_str_cat(undumped, s++, 1);
        }
    }

    RB_GC_GUARD(str);

    return undumped;
invalid_format:
    rb_raise(rb_eRuntimeError, "invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
}

Обратная операция к String#dump; возвращает копию self, отменяя изменения, выполненные методом String#dump.

Связанные материалы: см. Преобразование в новую строку.

unicode_normalize(form = :nfc) → string Показать исходный код
static VALUE
rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
{
    return unicode_normalize_common(argc, argv, str, id_normalize);
}

Возвращает копию self с применённой нормализацией Unicode.

Аргумент form должен быть одним из следующих символов (см. формы нормализации Unicode):

  • :nfc: каноническое разложение с последующей канонической композицией.

  • :nfd: каноническое разложение.

  • :nfkc: разложение по совместимости с последующей канонической композицией.

  • :nfkd: разложение по совместимости.

Кодировка self должна быть одной из следующих:

  • Encoding::UTF_8.

  • Encoding::UTF_16BE.

  • Encoding::UTF_16LE.

  • Encoding::UTF_32BE.

  • Encoding::UTF_32LE.

  • Encoding::GB18030.

  • Encoding::UCS_2BE.

  • Encoding::UCS_4BE.

Примеры:

"a\u0300".unicode_normalize       # => "à"  # Lowercase 'a' with grave accens.
"a\u0300".unicode_normalize(:nfd) # => "à"  # Same.

Связанные материалы: см. Преобразование в новую строку.

unicode_normalize!(form = :nfc) → self Показать исходный код
static VALUE
rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
{
    return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
}

Подобно String#unicode_normalize, но нормализация выполняется непосредственно над self (а не над его копией self).

Связанные материалы: см. Изменение.

unicode_normalized?(form = :nfc) → true or false Показать исходный код
static VALUE
rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
{
    return unicode_normalize_common(argc, argv, str, id_normalized_p);
}

Возвращает информацию о том, находится ли self в указанной form нормализации Unicode; см. String#unicode_normalize.

Значение form должно быть одним из :nfc, :nfd, :nfkc или :nfkd.

Примеры:

"a\u0300".unicode_normalized?       # => false
"a\u0300".unicode_normalized?(:nfd) # => true
"\u00E0".unicode_normalized?        # => true
"\u00E0".unicode_normalized?(:nfd)  # => false

Вызывает исключение, если self не имеет кодировки Unicode:

s = "\xE0".force_encoding(Encoding::ISO_8859_1)
s.unicode_normalized? # Raises Encoding::CompatibilityError

Связанные материалы: см. Проверка.

unpack(template, offset: 0) {|o| .... } → object Показать исходный код
unpack(template, offset: 0) → array
# File pack.rb, line 25
def unpack(fmt, offset: 0)
  Primitive.attr! :use_block
  Primitive.pack_unpack(fmt, offset)
end

Извлекает данные из self для создания новых объектов; см. Упакованные данные.

Если передан блок, вызывает его для каждого распакованного объекта.

Если блок не передан, возвращает массив, содержащий распакованные объекты.

Связанные материалы: см. Преобразование в объект, не являющийся строкой.

unpack1(template, offset: 0) → object Показать исходный код
# File pack.rb, line 37
def unpack1(fmt, offset: 0)
  Primitive.pack_unpack1(fmt, offset)
end

Подобно String#unpack без блока, но распаковывает и возвращает только первый извлечённый объект. См. Упакованные данные.

Связанные материалы: см. Преобразование в объект, не являющийся строкой.

upcase(mapping = :ascii) → new_string Показать исходный код
static VALUE
rb_str_upcase(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
    VALUE ret;

    flags = check_case_options(argc, argv, flags);
    enc = str_true_enc(str);
    if (case_option_single_p(flags, enc, str)) {
        ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
        str_enc_copy_direct(ret, str);
        upcase_single(ret);
    }
    else if (flags&ONIGENC_CASE_ASCII_ONLY) {
        ret = rb_str_new(0, RSTRING_LEN(str));
        rb_str_ascii_casemap(str, ret, &flags, enc);
    }
    else {
        ret = rb_str_casemap(str, &flags, enc);
    }

    return ret;
}

Возвращает новую строку, содержащую символы self в верхнем регистре:

'hello'.upcase        # => "HELLO"
'straße'.upcase       # => "STRASSE"
'привет'.upcase       # => "ПРИВЕТ"
'RubyGems.org'.upcase # => "RUBYGEMS.ORG"

Длины self и результата преобразования в верхний регистр могут различаться:

s = 'Straße'
s.size        # => 6
s.upcase      # => "STRASSE"
s.upcase.size # => 7

У некоторых символов (и некоторых наборов символов) нет вариантов в верхнем и нижнем регистре; см. Изменение регистра:

s = '1, 2, 3, ...'
s.upcase == s # => true
s = 'こんにちは'
s.upcase == s # => true

Преобразование регистра зависит от указанного mapping, которым может быть :ascii, :fold или :turkic; см. Преобразования регистра.

Связанные материалы: см. Преобразование в новую строку.

upcase!(mapping) → self or nil Показать исходный код
static VALUE
rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;

    flags = check_case_options(argc, argv, flags);
    str_modify_keep_cr(str);
    enc = str_true_enc(str);
    if (case_option_single_p(flags, enc, str)) {
        if (upcase_single(str))
            flags |= ONIGENC_CASE_MODIFIED;
    }
    else if (flags&ONIGENC_CASE_ASCII_ONLY)
        rb_str_ascii_casemap(str, str, &flags, enc);
    else
        str_shared_replace(str, rb_str_casemap(str, &flags, enc));

    if (ONIGENC_CASE_MODIFIED&flags) return str;
    return Qnil;
}

Подобно String#upcase, но:

  • Изменяет регистр символов непосредственно в self (а не в его копии self).

  • Возвращает self, если были внесены изменения, иначе возвращает nil.

Связанные материалы: см. Изменение.

upto(other_string, exclusive = false) {|string| ... } → self Показать исходный код
upto(other_string, exclusive = false) → new_enumerator
static VALUE
rb_str_upto(int argc, VALUE *argv, VALUE beg)
{
    VALUE end, exclusive;

    rb_scan_args(argc, argv, "11", &end, &exclusive);
    RETURN_ENUMERATOR(beg, argc, argv);
    return rb_str_upto_each(beg, end, RTEST(exclusive), str_upto_i, Qnil);
}

Если передан блок, вызывает его для каждого значения String, возвращаемого последовательными вызовами String#succ; первое значение — self, следующее — self.succ и так далее; последовательность завершается при достижении значения other_string; возвращает self:

a = []
'a'.upto('f') {|c| a.push(c) }
a # => ["a", "b", "c", "d", "e", "f"]

a = []
'Ж'.upto('П') {|c| a.push(c) }
a # => ["Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П"]

a = []
'よ'.upto('ろ') {|c| a.push(c) }
a # => ["よ", "ら", "り", "る", "れ", "ろ"]

a = []
'a8'.upto('b6') {|c| a.push(c) }
a # => ["a8", "a9", "b0", "b1", "b2", "b3", "b4", "b5", "b6"]

Если аргумент exclusive задан как истинный объект, последнее значение пропускается:

a = []
'a'.upto('f', true) {|c| a.push(c) }
a # => ["a", "b", "c", "d", "e"]

Если other_string не будет достигнуто, блок не вызывается:

'25'.upto('5') {|s| fail s }
'aa'.upto('a') {|s| fail s }

Если блок не передан, возвращает новый Enumerator:

'a8'.upto('b6') # => #<Enumerator: "a8":upto("b6")>

Связанные материалы: см. Итерация.

valid_encoding? → true or false Показать исходный код
static VALUE
rb_str_valid_encoding_p(VALUE str)
{
    int cr = rb_enc_str_coderange(str);

    return RBOOL(cr != ENC_CODERANGE_BROKEN);
}

Возвращает информацию о том, правильно ли закодирован self:

s = 'Straße'
s.valid_encoding?                                 # => true
s.encoding                                        # => #<Encoding:UTF-8>
s.force_encoding(Encoding::ASCII).valid_encoding? # => false

Связанные материалы: см. Проверка.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API