Spec-Zone.ru › Ruby 3.4

Класс 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.

Обратите внимание: \\ интерпретируется как escape-последовательность, то есть как одиночная обратная косая черта.

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

Перед обратной ссылкой обычно ставится дополнительная обратная косая черта. Например, чтобы записать обратную ссылку \& в 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

Срез строки — это подстрока, выбранная по определённым критериям.

Следующие методы экземпляра используют срезы:

  • String#[] (псевдоним String#slice): возвращает срез, скопированный из self.

  • String#[]=: изменяет self, заменяя указанный срез.

  • String#slice!: изменяет self, удаляя срез, и возвращает удалённый срез.

Каждый из приведённых выше методов принимает аргументы, определяющие срез для копирования или замены.

Аргументы могут задаваться в нескольких формах. Для строки string используются следующие формы:

  • string[index]

  • string[start, length]

  • string[range]

  • string[regexp, capture = 0]

  • string[substring]

string[index]

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

'bar'[0]      # => "b"
'bar'[2]      # => "r"
'bar'[20]     # => nil
'тест'[2]     # => "с"
'こんにちは'[4] # => "は"

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

'bar'[-3]      # => "b"
'bar'[-1]      # => "r"
'bar'[-20]     # => nil

string[start, length]

Если заданы неотрицательные целочисленные аргументы start и length, срез начинается со смещения start по символам, если оно существует, и продолжается на length символов, если они доступны:

'foo'[0, 2]      # => "fo"
'тест'[1, 2]     # => "ес"
'こんにちは'[2, 2] # => "にち"
# Zero length.
'foo'[2, 0]      # => ""
# Length not entirely available.
'foo'[1, 200]    # => "oo"
# Start out of range.
'foo'[4, 2]      # => nil

Частный случай: если start равно длине self, срезом будет новая пустая строка:

'foo'[3, 2]    # => ""
'foo'[3, 200]  # => ""

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

'foo'[-2, 2]     # => "oo"
'foo'[-2, 200]   # => "oo"
# Start out of range.
'foo'[-4, 2]     # => nil

Если задано отрицательное length, среза нет:

'foo'[1, -1]   # => nil
'foo'[-2, -1]  # => nil

string[range]

Если задан аргумент типа Range range, он создаёт подстроку string, используя индексы из range. Затем срез определяется описанным выше способом:

'foo'[0..1]     # => "fo"
'foo'[0, 2]     # => "fo"

'foo'[2...2]    # => ""
'foo'[2, 0]     # => ""

'foo'[1..200]   # => "oo"
'foo'[1, 200]   # => "oo"

'foo'[4..5]     # => nil
'foo'[4, 2]     # => nil

'foo'[-4..-3]   # => nil
'foo'[-4, 2]    # => nil

'foo'[3..4]     # => ""
'foo'[3, 2]     # => ""

'foo'[-2..-1]   # => "oo"
'foo'[-2, 2]    # => "oo"

'foo'[-2..197]  # => "oo"
'foo'[-2, 200]  # => "oo"

string[regexp, capture = 0]

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

'foo'[/o/]                # => "o"
'foo'[/x/]                # => nil
s = 'hello there'
s[/[aeiou](.)\1/]        # => "ell"
s[/[aeiou](.)\1/, 0]     # => "ell"

Если аргумент capture задан и не равен 0, он должен быть индексом захваченной группы (целым числом) или именем захваченной группы (String или Symbol); срезом будет указанная захваченная группа (см. раздел «Группы» в Regexp и захваты):

s = 'hello there'
s[/[aeiou](.)\1/, 1] # => "l"
s[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] # => "l"
s[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, :vowel]      # => "e"

Если задан недопустимый индекс захваченной группы, среза не будет. Если задано недопустимое имя захваченной группы, будет вызвано исключение IndexError.

string[substring]

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

'foo'['oo'] # => "oo"
'foo'['xx'] # => nil

Что здесь

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

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

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

Здесь класс String предоставляет методы для:

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

  • замороженных и незамороженных строк

  • получения данных

  • сравнения

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

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

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

  • перебора

Методы создания String

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

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

Методы для замороженных и незамороженных String

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

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

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

Методы получения данных

Количество

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

  • empty?: возвращает true, если self.length равно нулю; false в противном случае.

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

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

Подстроки

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

  • 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?: Возвращает true, если строка равна заданной строке после приведения регистра Unicode; в противном случае возвращает false.

Методы изменения String

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

Вставка

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

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

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

Замена

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

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

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

  • initialize_copy (также доступен под именем 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!: Нормализует self согласно Unicode; возвращает self.

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

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

Удаление

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

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

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

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

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

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

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

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

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

Методы преобразования в новую String

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

Расширение

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

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

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

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

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

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

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

Кодировка

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

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

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

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

Замена

  • dump: Возвращает копию self, в которой все непечатаемые символы заменены записью xHH, а все специальные символы экранированы.

  • undump: Возвращает копию self, в которой все записи \xNN заменены записями \uNNNN, а все экранированные символы преобразованы обратно.

  • 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_i: Возвращает целочисленное значение начальных символов, интерпретируемых как целое число.

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

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

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

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

Методы перебора

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

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

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

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

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

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

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

new(string = '', **opts) → 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.

Без аргументов возвращает пустую строку с кодировкой Encoding ASCII-8BIT:

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

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

String.new('foo')               # => "foo"
String.new('тест')              # => "тест"
String.new('こんにちは')          # => "こんにちは"

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

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

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 (или пустую строку, если string не задан); заданный capacity носит лишь рекомендательный характер и может повлиять или не повлиять на размер внутреннего буфера, что, в свою очередь, может повлиять на производительность:

String.new(capacity: 1)
String.new('foo', capacity: 4096)

Обратите внимание, что строки Ruby внутри программы завершаются нулевым байтом, поэтому размер внутреннего буфера будет на один или несколько байтов больше запрошенной ёмкости в зависимости от кодировки.

Аргументы string, encoding и capacity можно использовать одновременно:

String.new('hello', encoding: 'UTF-8', capacity: 25)
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 является объектом String, возвращает object.

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

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

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

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

string % 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 (подробности форматирования см. в Kernel#sprintf):

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

Если self содержит несколько подстановок, object должен быть Array или Hash, содержащим подставляемые значения:

"%-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"
string * integer → 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;
}

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

"Ho! " * 3 # => "Ho! Ho! Ho! "
"Ho! " * 0 # => ""
string + 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;
}

Возвращает новую String, содержащую 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, которая не заморожена.

-string → 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);
}

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

Возвращённая String будет дедуплицирована, если у неё не заданы переменные экземпляра и она не является подклассом String.

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

FILENAME = -'config/database.yml'

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

@url_list.concat(urls.map(&:dedup))
Также имеет псевдоним: dedup
string << object → string Показать исходный код
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:

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

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

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

Если эту кодовую точку нельзя представить в кодировке string, возникает исключение RangeError.

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

Если кодировка — US-ASCII, а кодовая точка находится в диапазоне 0..0xff, string автоматически преобразуется в ASCII-8BIT.

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

См. также: String#concat, принимающий несколько аргументов.

string <=> other_string → -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_string, возвращая:

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

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

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

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

Примеры:

'foo' <=> 'foo' # => 0
'foo' <=> 'food' # => -1
'food' <=> 'foo' # => 1
'FOO' <=> 'foo' # => -1
'foo' <=> 'FOO' # => 1
'foo' <=> 1 # => nil
string == 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);
}

Возвращает true, если object имеет ту же длину и содержимое, что и self; в противном случае возвращает false:

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

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

"\u{e4 f6 fc}".encode("ISO-8859-1") == ("\u{c4 d6 dc}") # => false

Если object не является экземпляром String, но отвечает на вызов to_str, строки сравниваются с помощью object.==.

Также имеет псевдоним: ===
string === object → true or false

Возвращает true, если object имеет ту же длину и содержимое, что и self; в противном случае возвращает false:

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

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

"\u{e4 f6 fc}".encode("ISO-8859-1") == ("\u{c4 d6 dc}") # => false

Если object не является экземпляром String, но отвечает на вызов to_str, строки сравниваются с помощью object.==.

Псевдоним для: ==
string =~ regexp → integer or nil Показать исходный код
string =~ 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);
    }
}

Возвращает индекс Integer первой подстроки, соответствующей заданному regexp, или nil, если совпадение не найдено:

'foo' =~ /f/ # => 0
'foo' =~ /o/ # => 1
'foo' =~ /x/ # => nil

Примечание: также обновляет глобальные переменные в Regexp.

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

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

number= nil
"no. 9" =~ /(?<number>\d+)/
number # => nil (not assigned)
/(?<number>\d+)/ =~ "no. 9"
number #=> "9"
string[index] → new_string or nil Показать исходный код
string[start, length] → new_string or nil
string[range] → new_string or nil
string[regexp, capture = 0] → new_string or nil
string[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, указанную аргументами. Примеры см. в разделе Фрагменты строк.

Также имеет псевдоним: slice
string[index] = new_string Показать исходный код
string[start, length] = new_string
string[range] = new_string
string[regexp, capture = 0] = new_string
string[substring] = 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, его часть или ничего не заменяет; возвращает new_string. См. раздел Фрагменты строк.

Несколько примеров:

s = 'foo'
s[2] = 'rtune'     # => "rtune"
s                  # => "fortune"
s[1, 5] = 'init'   # => "init"
s                  # => "finite"
s[3..4] = 'al'     # => "al"
s                  # => "finale"
s[/e$/] = 'ly'     # => "ly"
s                  # => "finally"
s['lly'] = 'ncial' # => "ncial"
s                  # => "financial"
append_as_bytes(*objects) → string Показать исходный код
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 predominently 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

Для каждого заданного объекта object, являющегося Integer, значение считается байтом. Если Integer больше одного байта, учитывается только младший байт, как и в String#setbyte:

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

См. также: String#<<, String#concat, которые выполняют конкатенацию с учётом кодировки.

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);
}

Возвращает true, если self содержит только символы ASCII, и false в противном случае:

'abc'.ascii_only?         # => true
"abc\u{6666}".ascii_only? # => false
b → 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(substring, offset = 0) → integer or nil Показать исходный код
byteindex(regexp, 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;
}

Возвращает Integer индекс в байтах первого вхождения указанного substring или nil, если совпадение не найдено:

'foo'.byteindex('f') # => 0
'foo'.byteindex('o') # => 1
'foo'.byteindex('oo') # => 1
'foo'.byteindex('ooo') # => nil

Возвращает Integer индекс в байтах первого совпадения с указанным Regexp regexp или nil, если совпадение не найдено:

'foo'.byteindex(/f/) # => 0
'foo'.byteindex(/o/) # => 1
'foo'.byteindex(/oo/) # => 1
'foo'.byteindex(/ooo/) # => nil

Аргумент Integer offset, если он указан, задаёт позицию в строке в байтах, с которой начинается поиск:

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

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

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

Если offset не указывает на границу символа (кодовой точки), вызывается исключение IndexError.

Связанные методы: String#index, String#byterindex.

byterindex(substring, offset = self.bytesize) → integer or nil Показать исходный код
byterindex(regexp, 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;
}

Возвращает Integer индекс в байтах последнего вхождения указанного substring или nil, если совпадение не найдено:

'foo'.byterindex('f') # => 0
'foo'.byterindex('o') # => 2
'foo'.byterindex('oo') # => 1
'foo'.byterindex('ooo') # => nil

Возвращает Integer индекс в байтах последнего совпадения с указанным Regexp regexp или nil, если совпадение не найдено:

'foo'.byterindex(/f/) # => 0
'foo'.byterindex(/o/) # => 2
'foo'.byterindex(/oo/) # => 1
'foo'.byterindex(/ooo/) # => nil

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

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

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

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

Или использовать String#byteindex с отрицательным просмотром вперёд.

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

Аргумент Integer offset, если он указан и неотрицателен, задаёт максимальную начальную позицию в строке в байтах, до которой нужно завершить поиск:

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

Если offset — отрицательное значение Integer, максимальная начальная позиция в строке, до которой нужно завершить поиск, равна сумме длины строки и offset:

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

Если offset не указывает на границу символа (кодовой точки), вызывается исключение IndexError.

Связанный метод: String#byteindex.

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  # => [209, 130, 208, 181, 209, 129, 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:

'foo'.bytesize        # => 3
'тест'.bytesize       # => 8
'こんにちは'.bytesize   # => 15

Сравните с String#length:

'foo'.length       # => 3
'тест'.length      # => 4
'こんにちは'.length  # => 5
byteslice(index, 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, если подстроку невозможно создать.

Если заданы целочисленные аргументы index и length, возвращает подстроку, начинающуюся с указанного index и имеющую заданную length (если это возможно), или nil, если length отрицателен либо index выходит за пределы self:

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

В обоих приведённых выше случаях, если index отрицателен, отсчёт ведётся от конца 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

Во всех случаях возвращаемая строка имеет ту же кодировку, что и self:

s.encoding              # => #<Encoding:UTF-8>
s.byteslice(4).encoding # => #<Encoding:UTF-8>
bytesplice(index, length, str) → string Показать исходный код
bytesplice(index, length, str, str_index, str_length) → string
bytesplice(range, str) → string
bytesplice(range, str, str_range) → string
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. Затрагиваемая часть строки определяется по тем же правилам, что и для String#byteslice, за исключением того, что length нельзя опустить. Если длина строки-замены отличается от длины заменяемого текста, длина строки будет соответствующим образом изменена.

Если указаны str_index и str_length либо str_range, содержимое self заменяется результатом str.byteslice(str_index, str_length) или str.byteslice(str_range); однако подстрока str не выделяется как новая строка.

Вариант, принимающий Integer, вызовет исключение IndexError, если значение выходит за допустимый диапазон; вариант с Range вызовет исключение RangeError. Если начальное или конечное смещение не указывает на границу символа (кодовой точки), будет вызвано исключение IndexError.

capitalize(*options) → 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; первый символ переводится в верхний регистр, остальные — в нижний:

s = 'hello World!' # => "hello World!"
s.capitalize       # => "Hello world!"

Регистр символов может зависеть от заданного options; см. Преобразование регистра.

Связанный метод: String#capitalize!.

capitalize!(*options) → 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;
}

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

s = 'hello World!' # => "hello World!"
s.capitalize!      # => "Hello world!"
s                  # => "Hello world!"
s.capitalize!      # => nil

Регистр символов может зависеть от заданного options; см. Преобразование регистра.

Связанный метод: String#capitalize.

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.downcase и other_string.downcase; возвращает:

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

  • 0, если значения равны.

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

  • nil, если значения несравнимы.

Примеры:

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

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

Связанный метод: String#casecmp?.

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:

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

Возвращает nil, если значения несравнимы:

'foo'.casecmp?(1) # => nil

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

Связанный метод: String#casecmp.

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(10)       # => "  hello   "
'  hello'.center(10)     # => "   hello  "
'hello'.center(10, 'ab') # => "abhelloaba"
'тест'.center(10)        # => "   тест   "
'こんにちは'.center(10)    # => "  こんにちは   "

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

'hello'.center(5)  # => "hello"
'hello'.center(1)  # => "hello"

Связанные методы: String#ljust, String#rjust.

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 # => ["こ", "ん", "に", "ち", "は"]
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('d')  # => "abc"
'abcdd'.chomp('d') # => "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 на месте; возвращает nil, если изменений не было, и self в противном случае.

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 на месте; возвращает nil, если self пуст, и self в противном случае.

Связанный метод: String#chomp!.

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

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

s = 'foo' # => "foo"
s.chr     # => "f"
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' # => "foo"
s.clear   # => ""
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]
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:

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

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

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

Связанный метод: String#<<, принимающий один аргумент.

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, соответствующих заданным selectors (см. Несколько селекторов символов):

a = "hello world"
a.count "lo"                   #=> 5
a.count "lo", "o"              #=> 2
a.count "hello", "^l"          #=> 4
a.count "ej-m"                 #=> 4

"hello^world".count "\\^aeiou" #=> 4
"hello-world".count "a\\-eo"   #=> 4

c = "hello world\\r\\n"
c.count "\\"                   #=> 2
c.count "\\A"                  #=> 0
c.count "X-\\w"                #=> 3
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
    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
    crypt_mutex_initialize();
    rb_nativethread_lock_lock(&crypt_mutex.lock);
    res = crypt(s, saltp);
#endif
    if (!res) {
        int err = errno;
        CRYPT_END();
        rb_syserr_fail(err, "crypt");
    }
    result = rb_str_new_cstr(res);
    CRYPT_END();
    return result;
}

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

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

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

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

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

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

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

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

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

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

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

-string → frozen_string
dedup → frozen_string

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

Возвращённая String будет дедуплицирована, если у неё не заданы переменные экземпляра и она не является подклассом String.

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

FILENAME = -'config/database.yml'

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

@url_list.concat(urls.map(&:dedup))
Псевдоним для: -@
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 (см. Несколько селекторов символов):

"hello".delete "l","lo"        #=> "heo"
"hello".delete "lo"            #=> "he"
"hello".delete "aeiou", "^e"   #=> "hell"
"hello".delete "ej-m"          #=> "ho"
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:

'hello'.delete_prefix('hel')      # => "lo"
'hello'.delete_prefix('llo')      # => "hello"
'тест'.delete_prefix('те')        # => "ст"
'こんにちは'.delete_prefix('こん')  # => "にちは"

Связанные методы: String#delete_prefix!, String#delete_suffix.

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:

'hello'.delete_suffix('llo')      # => "he"
'hello'.delete_suffix('hel')      # => "hello"
'тест'.delete_suffix('ст')        # => "те"
'こんにちは'.delete_suffix('ちは')  # => "こんに"

Связанные методы: String#delete_suffix!, String#delete_prefix.

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(*options) → 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 в нижнем регистре:

s = 'Hello World!' # => "Hello World!"
s.downcase         # => "hello world!"

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

Связанные методы: String#downcase!, String#upcase, String#upcase!.

downcase!(*options) → 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;
}

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

s = 'Hello World!' # => "Hello World!"
s.downcase!        # => "hello world!"
s                  # => "hello world!"
s.downcase!        # => nil

На регистр может влиять заданный options; см. Преобразование регистра.

См. также: String#downcase, String#upcase, String#upcase!.

dump → 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;
}

Возвращает печатное представление self, заключённое в двойные кавычки, со специальными символами в экранированном виде и непечатаемыми символами, представленными в шестнадцатеричной нотации:

"hello \n ''".dump    # => "\"hello \\n ''\""
"\f\x00\xff\\\"".dump # => "\"\\f\\x00\\xFF\\\\\\\"\""

См. также: String#undump (обратная операция для String#dump).

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:

'hello'.each_byte {|byte| print byte, ' ' }
print "\n"
'тест'.each_byte {|byte| print byte, ' ' }
print "\n"
'こんにちは'.each_byte {|byte| print byte, ' ' }
print "\n"

Вывод:

104 101 108 108 111
209 130 208 181 209 129 209 130
227 129 147 227 130 147 227 129 171 227 129 161 227 129 175

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

each_char {|c| ... } → 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:

'hello'.each_char {|char| print char, ' ' }
print "\n"
'тест'.each_char {|char| print char, ' ' }
print "\n"
'こんにちは'.each_char {|char| print char, ' ' }
print "\n"

Вывод:

h e l l o
т е с т
こ ん に ち は

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

each_codepoint {|integer| ... } → 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:

'hello'.each_codepoint {|codepoint| print codepoint, ' ' }
print "\n"
'тест'.each_codepoint {|codepoint| print codepoint, ' ' }
print "\n"
'こんにちは'.each_codepoint {|codepoint| print codepoint, ' ' }
print "\n"

Вывод:

104 101 108 108 111
1090 1077 1089 1090
12371 12435 12395 12385 12399

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

each_grapheme_cluster {|gc| ... } → 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:

s = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
s.each_grapheme_cluster {|gc| print gc, ' ' }

Вывод:

ä - p q r - b̈ - x y z - c̈

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

each_line(line_sep = $/, chomp: false) {|substring| ... } → self Показать исходный код
each_line(line_sep = $/, 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 при каждом вхождении заданного разделителя строк line_sep; передаёт каждую строку блоку и возвращает self:

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"

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

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

Вывод:

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

Если chomp имеет значение true, удаляет завершающий line_sep из каждой строки:

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."

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

s.each_line('') {|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);
}

Возвращает true, если длина self равна нулю, и false в противном случае:

"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, представляющий кодировку obj.

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.

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

'hello'.end_with?('ello')               #=> true
'hello'.end_with?('heaven', 'ello')     #=> true
'hello'.end_with?('heaven', 'paradise') #=> false
'тест'.end_with?('т')                   # => true
'こんにちは'.end_with?('は')              # => true

См. также: String#start_with?.

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);
}

Возвращает true, если object имеет ту же длину и содержимое, что и self; в противном случае возвращает false:

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

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

"\u{e4 f6 fc}".encode("ISO-8859-1").eql?("\u{c4 d6 dc}") # => 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.bytes                   # => [197, 130, 97, 197, 130]

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

s.valid_encoding?                 # => false
s.force_encoding(Encoding::UTF_8) # => "łał"
s.valid_encoding?                 # => true
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, отсчитываемому с нуля, в виде целого числа или nil, если index находится вне допустимого диапазона:

s = 'abcde'   # => "abcde"
s.getbyte(0)  # => 97
s.getbyte(-1) # => 101
s.getbyte(5)  # => nil

См. также: String#setbyte.

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 = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
s.grapheme_clusters
# => ["ä", "-", "p", "q", "r", "-", "b̈", "-", "x", "y", "z", "-", "c̈"]
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 заменены.

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

Возвращает Enumerator, если replacement не задан и блок не передан.

Связанные методы: String#sub, String#sub!, String#gsub!.

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);
}

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

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

Возвращает Enumerator, если replacement не задан и блок не передан.

Связанные методы: String#sub, String#gsub, String#sub!.

hash → integer Показать исходный код
static VALUE
rb_str_hash_m(VALUE str)
{
    st_index_t hval = rb_str_hash(str);
    return ST2FIX(hval);
}

Возвращает целочисленное хеш-значение для self. Значение зависит от длины, содержимого и кодировки self.

Связанный метод: Object#hash.

hex → integer Показать исходный код
static VALUE
rb_str_hex(VALUE str)
{
    return rb_str_to_inum(str, 16, FALSE);
}

Интерпретирует начальную подстроку self как строку шестнадцатеричных цифр (с необязательным знаком и необязательным 0x) и возвращает соответствующее число; если такой начальной подстроки нет, возвращает ноль:

'0x0a'.hex        # => 10
'-1234'.hex       # => -4660
'0'.hex           # => 0
'non-numeric'.hex # => 0

Связанный метод: String#oct.

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);
}

Возвращает true, если self содержит other_string, и false в противном случае:

s = 'foo'
s.include?('f')    # => true
s.include?('fo')   # => true
s.include?('food') # => false
index(substring, offset = 0) → integer or nil Показать исходный код
index(regexp, 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;
}

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

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

'foo'.index('f')         # => 0
'foo'.index('o')         # => 1
'foo'.index('oo')        # => 1
'foo'.index('ooo')       # => nil
'тест'.index('с')        # => 2
'こんにちは'.index('ち')   # => 3

Если аргументом является Regexp regexp, возвращает индекс первого совпадения в self:

'foo'.index(/o./) # => 1
'foo'.index(/.o/) # => 0

Если offset — положительное целое число, поиск начинается с позиции offset:

'foo'.index('o', 1)        # => 1
'foo'.index('o', 2)        # => 2
'foo'.index('o', 3)        # => nil
'тест'.index('с', 1)       # => 2
'こんにちは'.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

Связанный метод: String#rindex.

initialize_copy Показать исходный код
Также имеет псевдоним: replace
insert(index, 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 — положительное Integer, вставляет other_string со смещением index:

'foo'.insert(1, 'bar') # => "fbaroo"

Если index — отрицательное Integer, отсчитывает позицию назад от конца self и вставляет other_string со смещением index+1 (то есть после self[index]):

'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, заключённое в двойные кавычки, со специальными символами, записанными с использованием escape-последовательностей:

s = "foo\tbar\tbaz\n"
s.inspect
# => "\"foo\\tbar\\tbaz\\n\""
intern → symbol Показать исходный код
VALUE
rb_str_intern(VALUE str)
{
    VALUE sym;

    GLOBAL_SYMBOLS_ENTER(symbols);
    {
        sym = lookup_str_sym_with_lock(symbols, str);

        if (sym) {
            // ok
        }
        else if (USE_SYMBOL_GC) {
            rb_encoding *enc = rb_enc_get(str);
            rb_encoding *ascii = rb_usascii_encoding();
            if (enc != ascii && sym_check_asciionly(str, false)) {
                str = rb_str_dup(str);
                rb_enc_associate(str, ascii);
                OBJ_FREEZE(str);
                enc = ascii;
            }
            else {
                str = rb_str_dup(str);
                OBJ_FREEZE(str);
            }
            str = rb_fstring(str);
            int type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
            if (type < 0) type = ID_JUNK;
            sym = dsymbol_alloc(symbols, rb_cSymbol, str, enc, type);
        }
        else {
            ID id = intern_str(str, 0);
            sym = ID2SYM(id);
        }
    }
    GLOBAL_SYMBOLS_LEAVE();
    return sym;
}

Возвращает Symbol, соответствующий str, создавая символ, если он ещё не существовал. См. Symbol#id2name.

"Koala".intern         #=> :Koala
s = 'cat'.to_sym       #=> :cat
s == :cat              #=> true
s = '@cat'.to_sym      #=> :@cat
s == :@cat             #=> true

Этот метод также можно использовать для создания символов, которые нельзя представить с помощью нотации :xxx.

'cat and dog'.to_sym   #=> :"cat and dog"
Также имеет псевдоним: 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(Line_sep = $/, 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 на подстроки («строки») в соответствии с заданными аргументами (подробности см. в String#each_line); возвращает строки в виде массива.

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

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

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

'hello'.ljust(10)       # => "hello     "
'  hello'.ljust(10)     # => "  hello   "
'hello'.ljust(10, 'ab') # => "helloababa"
'тест'.ljust(10)        # => "тест      "
'こんにちは'.ljust(10)    # => "こんにちは     "

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

'hello'.ljust(5)  # => "hello"
'hello'.ljust(1)  # => "hello"

Связанные методы: String#rjust, String#center.

lstrip → new_string Показать исходный код
static VALUE
rb_str_lstrip(VALUE str)
{
    char *start;
    long len, loffset;
    RSTRING_GETMEM(str, start, len);
    loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
    if (loffset <= 0) return 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
s        # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
s.lstrip # => "abc\u0000\t\n\v\f\r "

Связанные методы: String#rstrip, String#strip.

lstrip! → self or nil Показать исходный код
static VALUE
rb_str_lstrip_bang(VALUE str)
{
    rb_encoding *enc;
    char *start, *s;
    long olen, loffset;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    RSTRING_GETMEM(str, start, olen);
    loffset = lstrip_offset(str, start, start+olen, enc);
    if (loffset > 0) {
        long len = olen-loffset;
        s = start + loffset;
        memmove(start, s, len);
        STR_SET_LEN(str, len);
        TERM_FILL(start+len, rb_enc_mbminlen(enc));
        return str;
    }
    return Qnil;
}

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

Связанные методы: String#rstrip!, String#strip!.

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 (или nil) на основе self и заданного pattern.

Примечание: также обновляет глобальные переменные в Regexp.

  • Вычисляет regexp, преобразуя pattern (если это ещё не Regexp).

    regexp = Regexp.new(pattern)
    
  • Вычисляет matchdata, которым будет либо объект MatchData, либо nil (см. Regexp#match):

    matchdata = <tt>regexp.match(self)

Если блок не передан, возвращает вычисленное значение matchdata:

'foo'.match('f') # => #<MatchData "f">
'foo'.match('o') # => #<MatchData "o">
'foo'.match('x') # => nil

Если задан аргумент Integer offset, поиск начинается с индекса offset:

'foo'.match('f', 1) # => nil
'foo'.match('o', 1) # => #<MatchData "o">

Если блок передан, вызывает его с вычисленным значением matchdata и возвращает значение, возвращённое блоком:

'foo'.match(/o/) {|matchdata| matchdata } # => #<MatchData "o">
'foo'.match(/x/) {|matchdata| matchdata } # => nil
'foo'.match(/f/, 1) {|matchdata| matchdata } # => 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);
}

Возвращает true или false в зависимости от того, найдено ли совпадение для self и pattern.

Примечание: не обновляет глобальные переменные в Regexp.

Вычисляет regexp, преобразуя pattern (если это ещё не Regexp).

regexp = Regexp.new(pattern)

Возвращает true, если self+.match(regexp) возвращает объект MatchData, и false в противном случае:

'foo'.match?(/o/) # => true
'foo'.match?('o') # => true
'foo'.match?(/x/) # => false

Если задан аргумент типа Integer offset, поиск начинается с индекса offset:

'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 как строку восьмеричных цифр (с необязательным знаком) и возвращает соответствующее число; если такой начальной подстроки нет, возвращает ноль:

'123'.oct             # => 83
'-377'.oct            # => -255
'0377non-numeric'.oct # => 255
'non-numeric'.oct     # => 0

Если self начинается с 0, учитываются индикаторы системы счисления; см. Kernel#Integer.

Связанный метод: String#hex.

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(string_or_regexp) → [head, match, tail] Показать исходный код
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.

Сопоставляет шаблон с self, выполняя поиск с начала. Шаблоном служит:

  • сам string_or_regexp, если это Regexp.

  • Regexp.quote(string_or_regexp), если string_or_regexp — строка.

Если шаблон найден, возвращает часть до совпадения, первое совпадение и часть после него:

'hello'.partition('l')      # => ["he", "l", "lo"]
'hello'.partition('ll')     # => ["he", "ll", "o"]
'hello'.partition('h')      # => ["", "h", "ello"]
'hello'.partition('o')      # => ["hell", "o", ""]
'hello'.partition(/l+/)     #=> ["he", "ll", "o"]
'hello'.partition('')       # => ["", "", "hello"]
'тест'.partition('т')       # => ["", "т", "ест"]
'こんにちは'.partition('に')  # => ["こん", "に", "ちは"]

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

'hello'.partition('x') # => ["hello", "", ""]

Связанные методы: String#rpartition, String#split.

prepend(*other_strings) → 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;
}

Добавляет каждую строку из other_strings в начало self и возвращает self:

s = 'foo'
s.prepend('bar', 'baz') # => "barbazfoo"
s                       # => "barbazfoo"

Связанный метод: String#concat.

replace(other_string) → self

Заменяет содержимое self содержимым other_string:

s = 'foo'        # => "foo"
s.replace('bar') # => "bar"
Псевдоним для: initialize_copy
reverse → 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 в обратном порядке.

'stressed'.reverse # => "desserts"
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 с символами в обратном порядке:

s = 'stressed'
s.reverse! # => "desserts"
s          # => "desserts"
rindex(substring, offset = self.length) → integer or nil Показать исходный код
rindex(regexp, 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;
}

Возвращает индекс типа Integer последнего вхождения заданного substring или nil, если совпадений нет:

'foo'.rindex('f') # => 0
'foo'.rindex('o') # => 2
'foo'.rindex('oo') # => 1
'foo'.rindex('ooo') # => nil

Возвращает индекс типа Integer последнего совпадения с заданным regexp типа Regexp или nil, если совпадений нет:

'foo'.rindex(/f/) # => 0
'foo'.rindex(/o/) # => 2
'foo'.rindex(/oo/) # => 1
'foo'.rindex(/ooo/) # => nil

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

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

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

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

Или использовать String#index с отрицательным просмотром вперёд.

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

Аргумент типа Integer offset, если он задан и неотрицателен, задаёт максимальную начальную позицию в строке, до которой поиск должен заканчиваться:

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

Если offset — отрицательное значение типа Integer, максимальная начальная позиция в строке, до которой поиск должен заканчиваться, равна сумме длины строки и offset:

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

Связанный метод: String#index.

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

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

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

'hello'.rjust(10)       # => "     hello"
'hello  '.rjust(10)     # => "   hello  "
'hello'.rjust(10, 'ab') # => "ababahello"
'тест'.rjust(10)        # => "      тест"
'こんにちは'.rjust(10)    # => "     こんにちは"

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

'hello'.rjust(5, 'ab')  # => "hello"
'hello'.rjust(1, 'ab')  # => "hello"

Связанные методы: String#ljust, String#center.

rpartition(sep) → [head, match, tail] Показать исходный код
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));
}

Возвращает массив из трёх подстрок self.

Сопоставляет шаблон с self, выполняя поиск в обратном направлении от конца. Шаблоном служит:

  • сам string_or_regexp, если это Regexp.

  • Regexp.quote(string_or_regexp), если string_or_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(/l+/)     # => ["hel", "l", "o"]
'hello'.rpartition('')       # => ["hello", "", ""]
'тест'.rpartition('т')       # => ["тес", "т", ""]
'こんにちは'.rpartition('に')  # => ["こん", "に", "ちは"]

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

'hello'.rpartition('x') # => ["", "", "hello"]

Связанные методы: String#partition, String#split.

rstrip → new_string Показать исходный код
static VALUE
rb_str_rstrip(VALUE str)
{
    rb_encoding *enc;
    char *start;
    long olen, roffset;

    enc = STR_ENC_GET(str);
    RSTRING_GETMEM(str, start, olen);
    roffset = rstrip_offset(str, start, start+olen, enc);

    if (roffset <= 0) return str_duplicate(rb_cString, str);
    return rb_str_subseq(str, 0, olen-roffset);
}

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

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"

Связанные методы: String#lstrip, String#strip.

rstrip! → self or nil Показать исходный код
static VALUE
rb_str_rstrip_bang(VALUE str)
{
    rb_encoding *enc;
    char *start;
    long olen, roffset;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    RSTRING_GETMEM(str, start, olen);
    roffset = rstrip_offset(str, start, start+olen, enc);
    if (roffset > 0) {
        long len = olen - roffset;

        STR_SET_LEN(str, len);
        TERM_FILL(start+len, rb_enc_mbminlen(enc));
        return str;
    }
    return Qnil;
}

Аналогичен String#rstrip, но все изменения выполняются в self; возвращает self, если были внесены изменения, и nil в противном случае.

Связанные методы: String#lstrip!, String#strip!.

scan(string_or_regexp) → array Показать исходный код
scan(string_or_regexp) {|matches| ... } → 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; шаблоном служит:

  • сам string_or_regexp, если это Regexp.

  • Regexp.quote(string_or_regexp), если string_or_regexp — строка.

Перебирает self, формируя набор результатов сопоставления:

  • Если шаблон не содержит групп, каждый результат представляет собой найденную строку, $&.

  • Если шаблон содержит группы, каждый результат представляет собой массив с одним элементом на каждую группу.

Если блок не задан, возвращает массив результатов:

s = 'cruel world'
s.scan(/\w+/)      # => ["cruel", "world"]
s.scan(/.../)      # => ["cru", "el ", "wor"]
s.scan(/(...)/)    # => [["cru"], ["el "], ["wor"]]
s.scan(/(..)(..)/) # => [["cr", "ue"], ["l ", "wo"]]

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

s.scan(/\w+/) {|w| print "<<#{w}>> " }
print "\n"
s.scan(/(.)(.)/) {|x,y| print y, x }
print "\n"

Вывод:

<<cruel>> <<world>>
rceu lowlr
scrub(replacement_string = default_replacement) → new_string Показать исходный код
scrub{|bytes| ... } → 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.

Если блок и аргумент не заданы, каждая недопустимая последовательность заменяется строкой замены по умолчанию ("�" для кодировки Unicode, в противном случае — '?'):

s = "foo\x81\x81bar"
s.scrub # => "foo��bar"

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

"foo\x81\x81bar".scrub('xyzzy') # => "fooxyzzyxyzzybar"

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

"foo\x81\x81bar".scrub {|bytes| p bytes; 'XYZZY' }
# => "fooXYZZYXYZZYbar"

Вывод:

"\x81"
"\x81"
scrub! → self Показать исходный код
scrub!(replacement_string = default_replacement) → self
scrub!{|bytes| ... } → 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.

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 = 'abcde'      # => "abcde"
s.setbyte(0, 98) # => 98
s                # => "bbcde"

Связанный метод: String#getbyte.

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;
}

Удаляет и возвращает подстроку из self, указанную аргументами. См. раздел Срезы строк.

Несколько примеров:

string = "This is a string"
string.slice!(2)        #=> "i"
string.slice!(3..6)     #=> " is "
string.slice!(/s.*t/)   #=> "sa st"
string.slice!("r")      #=> "r"
string                  #=> "Thing"
split(field_sep = $;, limit = 0) → array Показать исходный код
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, полученных при разделении self в каждом месте, где встречается заданный разделитель полей field_sep.

Если field_sep — $;:

  • Если $; — nil (значение по умолчанию), разделение выполняется так же, как если бы в качестве field_sep был указан пробел (см. ниже).

  • Если $; — строка, разделение выполняется так же, как если бы в качестве field_sep была указана эта строка (см. ниже).

Если field_sep — ' ', а limit — 0 (значение по умолчанию), разделение выполняется по каждой последовательности пробельных символов:

'abc def ghi'.split(' ')         => ["abc", "def", "ghi"]
"abc \n\tdef\t\n  ghi".split(' ') # => ["abc", "def", "ghi"]
'abc  def   ghi'.split(' ')      => ["abc", "def", "ghi"]
''.split(' ')                    => []

Если field_sep — строка, отличная от ' ', а limit — 0, разделение выполняется при каждом вхождении field_sep; завершающие пустые подстроки не возвращаются:

'abracadabra'.split('ab')  => ["", "racad", "ra"]
'aaabcdaaa'.split('a')     => ["", "", "", "bcd"]
''.split('a')              => []
'3.14159'.split('1')       => ["3.", "4", "59"]
'!@#$%^$&*($)_+'.split('$') # => ["!@#", "%^", "&*(", ")_+"]
'тест'.split('т')          => ["", "ес"]
'こんにちは'.split('に')     => ["こん", "ちは"]

Если field_sep — Regexp, а limit — 0, разделение выполняется при каждом совпадении; завершающие пустые подстроки не возвращаются:

'abracadabra'.split(/ab/) # => ["", "racad", "ra"]
'aaabcdaaa'.split(/a/)   => ["", "", "", "bcd"]
'aaabcdaaa'.split(//)    => ["a", "a", "a", "b", "c", "d", "a", "a", "a"]
'1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"]

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

'1:2:3'.split(/(:)()()/, 2) # => ["1", ":", "", "", "2:3"]

Как видно выше, если limit — 0, завершающие пустые подстроки не возвращаются:

'aaabcdaaa'.split('a')   => ["", "", "", "bcd"]

Если limit — положительное целое число n, выполняется не более n - 1- разделений, поэтому возвращается не более n подстрок; завершающие пустые подстроки включаются:

'aaabcdaaa'.split('a', 1) # => ["aaabcdaaa"]
'aaabcdaaa'.split('a', 2) # => ["", "aabcdaaa"]
'aaabcdaaa'.split('a', 5) # => ["", "", "", "bcd", "aa"]
'aaabcdaaa'.split('a', 7) # => ["", "", "", "bcd", "", "", ""]
'aaabcdaaa'.split('a', 8) # => ["", "", "", "bcd", "", "", ""]

Обратите внимание: если field_sep — Regexp, содержащий группы, их совпадения включаются в возвращаемый массив, но не учитываются при ограничении количества.

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

'aaabcdaaa'.split('a', -1) # => ["", "", "", "bcd", "", "", ""]

Если задан блок, он вызывается для каждой подстроки:

'abc def ghi'.split(' ') {|substring| p substring }

Вывод:

"abc"
"def"
"ghi"

Связанные методы: String#partition, String#rpartition.

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, «сжаты» (см. раздел Несколько селекторов символов):

«Сжатие» означает, что каждая последовательность из нескольких одинаковых выбранных символов сокращается до одного символа; если аргументы не заданы, сжимаются все символы:

"yellow moon".squeeze                  #=> "yelow mon"
"  now   is  the".squeeze(" ")         #=> " now is the"
"putters shoot balls".squeeze("m-z")   #=> "puters shot balls"
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, если были внесены изменения, и nil в противном случае.

start_with?(*string_or_regexp) → 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 с одной из заданных string_or_regexp.

Проверяет шаблоны в начале self. Для каждого заданного string_or_regexp шаблоном является:

  • само string_or_regexp, если это Regexp.

  • Regexp.quote(string_or_regexp), если string_or_regexp — строка.

Возвращает 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

Связанный метод: String#end_with?.

strip → new_string Показать исходный код
static VALUE
rb_str_strip(VALUE str)
{
    char *start;
    long olen, loffset, roffset;
    rb_encoding *enc = STR_ENC_GET(str);

    RSTRING_GETMEM(str, start, olen);
    loffset = lstrip_offset(str, start, start+olen, enc);
    roffset = rstrip_offset(str, start+loffset, start+olen, enc);

    if (loffset <= 0 && roffset <= 0) return str_duplicate(rb_cString, str);
    return rb_str_subseq(str, loffset, olen-loffset-roffset);
}

Возвращает копию объекта-получателя без начальных и конечных пробельных символов; см. раздел Пробельные символы в строках:

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.strip # => "abc"

Связанные методы: String#lstrip, String#rstrip.

strip! → self or nil Показать исходный код
static VALUE
rb_str_strip_bang(VALUE str)
{
    char *start;
    long olen, loffset, roffset;
    rb_encoding *enc;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    RSTRING_GETMEM(str, start, olen);
    loffset = lstrip_offset(str, start, start+olen, enc);
    roffset = rstrip_offset(str, start+loffset, start+olen, enc);

    if (loffset > 0 || roffset > 0) {
        long len = olen-roffset;
        if (loffset > 0) {
            len -= loffset;
            memmove(start, start + loffset, len);
        }
        STR_SET_LEN(str, len);
        TERM_FILL(start+len, rb_enc_mbminlen(enc));
        return str;
    }
    return Qnil;
}

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

Связанные методы: String#lstrip!, String#strip!.

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.

См. раздел Методы подстановки.

Связанные методы: String#sub!, String#gsub, String#gsub!.

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;
}

Заменяет первое вхождение (но не все вхождения) заданного pattern в self; возвращает self, если замена была выполнена, и nil в противном случае.

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

Связанные методы: String#sub, String#gsub, String#gsub!.

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 # => '**+'

Следующим после цифры является другая цифра; при переходе от 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
s # => "\x00\x00\x00"
s.succ # => "\x00\x00\x01"
s = 255.chr * 3
s # => "\xFF\xFF\xFF"
s.succ # => "\x01\x00\x00\x00"

Перенос может происходить между буквенно-цифровыми символами и внутри их сочетаний:

s = 'zz99zz99'
s.succ # => "aaa00aa00"
s = '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;
}

Возвращает простую контрольную сумму символов self длиной n бит; контрольная сумма представляет собой сумму двоичных значений каждого байта в self по модулю 2**n - 1:

'hello'.sum     # => 532
'hello'.sum(4)  # => 4
'hello'.sum(64) # => 532
'тест'.sum      # => 1405
'こんにちは'.sum  # => 2582

Эта контрольная сумма не отличается особой надёжностью.

swapcase(*options) → 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 с изменённым регистром: каждый символ в верхнем регистре преобразуется в нижний, а каждый символ в нижнем регистре — в верхний:

s = 'Hello World!' # => "Hello World!"
s.swapcase         # => "hELLO wORLD!"

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

Связанный метод: String#swapcase!.

swapcase!(*options) → 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;
}

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

s = 'Hello World!' # => "Hello World!"
s.swapcase!        # => "hELLO wORLD!"
s                  # => "hELLO wORLD!"
''.swapcase!       # => nil

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

Связанный метод: String#swapcase.

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;
}

Возвращает self, интерпретированную как объект Complex; начальные пробелы и лишние символы в конце игнорируются:

'9'.to_c                 # => (9+0i)
'2.5'.to_c               # => (2.5+0i)
'2.5/1'.to_c             # => ((5/2)+0i)
'-3/2'.to_c              # => ((-3/2)+0i)
'-i'.to_c                # => (0-1i)
'45i'.to_c               # => (0+45i)
'3-4i'.to_c              # => (3-4i)
'-4e2-4e-2i'.to_c        # => (-400.0-0.04i)
'-0.0-0.0i'.to_c         # => (-0.0-0.0i)
'1/2+3/4i'.to_c          # => ((1/2)+(3/4)*i)
'1.0@0'.to_c             # => (1+0.0i)
"1.0@#{Math::PI/2}".to_c # => (0.0+1i)
"1.0@#{Math::PI}".to_c   # => (-1+0.0i)

Если строку нельзя преобразовать, возвращает ноль типа Complex:

'ruby'.to_c        # => (0+0i)

См. Kernel#Complex.

to_f → float Показать исходный код
static VALUE
rb_str_to_f(VALUE str)
{
    return DBL2NUM(rb_str_to_dbl(str, FALSE));
}

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

'3.14159'.to_f  # => 3.14159
'1.234e-2'.to_f # => 0.01234

Символы после корректного числа в начале строки (в заданном base) игнорируются:

'3.14 (pi to two places)'.to_f # => 3.14

Если в начале строки нет корректного числа, возвращает ноль:

'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 (которая должна быть в диапазоне (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_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;
}

Возвращает результат интерпретации начальных символов в str как рационального числа. Начальные пробелы и лишние символы после корректного числа игнорируются. Последовательности цифр можно разделять символом подчёркивания. Если в начале str нет корректного числа, возвращается ноль. Этот метод никогда не вызывает исключение.

'  2  '.to_r       #=> (2/1)
'300/2'.to_r       #=> (150/1)
'-9.2'.to_r        #=> (-46/5)
'-9.2e2'.to_r      #=> (-920/1)
'1_234_567'.to_r   #=> (1234567/1)
'21 June 09'.to_r  #=> (21/1)
'21/06/09'.to_r    #=> (7/2)
'BWV 1079'.to_r    #=> (0/1)

ПРИМЕЧАНИЕ: “0.3”.to_r — не то же самое, что 0.3.to_r. Первый вариант эквивалентен “3/10”.to_r, а второй — нет.

"0.3".to_r == 3/10r  #=> true
0.3.to_r   == 3/10r  #=> false

См. также Kernel#Rational.

to_s → self or 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 → symbol

Возвращает Symbol, соответствующий str, создавая символ, если он ещё не существовал. См. Symbol#id2name.

"Koala".intern         #=> :Koala
s = 'cat'.to_sym       #=> :cat
s == :cat              #=> true
s = '@cat'.to_sym      #=> :@cat
s == :@cat             #=> true

Этот метод также можно использовать для создания символов, которые нельзя представить с помощью записи :xxx.

'cat and dog'.to_sym   #=> :"cat and dog"
Псевдоним для: 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 должны быть допустимыми селекторами символов (см. Селекторы символов) и могут использовать любую из допустимых форм, включая отрицание, диапазоны и экранирование:

# Negation.
'hello'.tr('^aeiou', '-') # => "-e--o"
# Ranges.
'ibm'.tr('b-z', 'a-z') # => "hal"
# Escapes.
'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, если были внесены изменения, и nil в противном случае.

tr_s(selector, replacements) → 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, но также удаляет повторяющиеся символы в изменённых частях преобразованной строки; возвращает новую строку (преобразованную и очищенную от повторяющихся символов).

'hello'.tr_s('l', 'r')   #=> "hero"
'hello'.tr_s('el', '-')  #=> "h-o"
'hello'.tr_s('el', 'hx') #=> "hhxo"

Связанный метод: String#squeeze.

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, если были внесены изменения, и nil в противном случае.

Связанный метод: String#squeeze!.

undump → 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");
}

Возвращает версию self без экранирования:

s_orig = "\f\x00\xff\\\""    # => "\f\u0000\xFF\\\""
s_dumped = s_orig.dump       # => "\"\\f\\x00\\xFF\\\\\\\"\""
s_undumped = s_dumped.undump # => "\f\u0000\xFF\\\""
s_undumped == s_orig         # => true

Связанный метод: String#dump (обратный к String#undump).

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      # => "a"
"\u00E0".unicode_normalize(:nfd) # => "a "

Связанные методы: String#unicode_normalize!, String#unicode_normalized?.

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.

Связанный метод: String#unicode_normalized?.

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);
}

Возвращает true, если self имеет заданную form нормализации Unicode, и false в противном случае. 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('ISO-8859-1')
s.unicode_normalized? # Raises Encoding::CompatibilityError.

Связанные методы: String#unicode_normalize, String#unicode_normalize!.

unpack(template, offset: 0, &block) → array Показать исходный код
# File pack.rb, line 23
def unpack(fmt, offset: 0)
  Primitive.attr! :use_block
  Primitive.pack_unpack(fmt, offset)
end

Извлекает данные из self.

Если block не задан, формирует объекты, которые становятся элементами нового массива, и возвращает этот массив. В противном случае передаёт каждый объект блоку.

См. Упакованные данные.

unpack1(template, offset: 0) → object Показать исходный код
# File pack.rb, line 33
def unpack1(fmt, offset: 0)
  Primitive.pack_unpack1(fmt, offset)
end

Подобно String#unpack, но распаковывает и возвращает только первый извлечённый объект. См. Упакованные данные.

upcase(*options) → 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 в верхнем регистре:

s = 'Hello World!' # => "Hello World!"
s.upcase           # => "HELLO WORLD!"

На регистр может влиять заданный options; см. Преобразование регистра.

Связанные методы: String#upcase!, String#downcase, String#downcase!.

upcase!(*options) → 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;
}

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

s = 'Hello World!' # => "Hello World!"
s.upcase!          # => "HELLO WORLD!"
s                  # => "HELLO WORLD!"
s.upcase!          # => nil

На регистр может влиять заданный options; см. Преобразование регистра.

Связанные методы: String#upcase, String#downcase, String#downcase!.

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:

'a8'.upto('b6') {|s| print s, ' ' } # => "a8"

Вывод:

a8 a9 b0 b1 b2 b3 b4 b5 b6

Если аргумент exclusive задан как истинное значение, последнее значение пропускается:

'a8'.upto('b6', true) {|s| print s, ' ' } # => "a8"

Вывод:

a8 a9 b0 b1 b2 b3 b4 b5

Если значение 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);
}

Возвращает true, если self закодирована корректно, и false в противном случае:

"\xc2\xa1".force_encoding("UTF-8").valid_encoding? # => true
"\xc2".force_encoding("UTF-8").valid_encoding?     # => false
"\x80".force_encoding("UTF-8").valid_encoding?     # => false

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API