Spec-Zone.ru › Ruby 3.4

класс String

Родитель:
Объект
Включенные модули:
Comparable

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

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

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

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

  • Литерала Here Document.

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

  • Метода String.

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

В общем случае, если существуют оба варианта метода (с и без знака «!»), метод с «!» изменяет объект, а метод без «!» — нет. Однако метод без «!» также может изменять объект, например, String#replace.

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

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

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

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

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

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

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

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

  • Одно из следующего:

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

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

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

Аргумент pattern

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

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

Когда pattern является строкой, все её символы обрабатываются как обычные символы (не как специальные символы Regexp):

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

String replacement

Если replacement является строкой, эта строка определяет заменяющую строку, которая подставляется вместо совпавшего текста.

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

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

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

  • \k<name> относится к именованному захвату name.

См. Regexp для подробностей.

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

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

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

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

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

См. Regexp для подробностей.

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

Обратите также внимание, что строковый литерал потребляет обратные слэши. См. Строковые литералы для подробностей о строковых литералах.

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

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

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

Хэш replacement

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

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

Обратите внимание, что символьный ключ не совпадает:

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

Блок

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

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

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

Пробелы в строках

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

  • NL (нуль): "\x00", "\u0000".

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

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

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

  • FF (форма подачи): "\x0c", "\f".

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

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

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

  • lstrip, lstrip!: Удаление начальных пробелов.

  • rstrip, rstrip!: Удаление конечных пробелов.

  • strip, strip!: Удаление начальных и конечных пробелов.

String Срезы

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

Эти методы экземпляров используют срезы:

  • 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"
END_OF_DOCUMENT_MARKER

Если аргумент 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.

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

Здесь класс 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 если строка в нормализованной форме Юникода; 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!: Нормализует Unicode self; возвращает 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 (aliased as 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 с удалёнными смежными повторяющимися символами.

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

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

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

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

  • to_s (aliased as 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.

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

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

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

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

(В отличие от String.new, строковая литерал, например, '' или строковая литерал типа «здесь документ», всегда имеет кодировку скрипта.)

С необязательным ключевым аргументом 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.

END_OF_DOCUMENT_MARKER

Общедоступные методы экземпляров

строка % объект → новая_строка
Исходный код
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"
строка * целое число → новая_строка
Исходный код
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 # => ""
строка + другая_строка → новая_строка
Исходный код
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"
+строка → новая_строка или 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, который не заморожен.

-строка → замороженная_строка
Исходный код
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))
Также алиас: дедуплицировать
строка << объект → строка
Исходный код
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!"

Если эта кодовая точка не может быть представлена в кодировке строки, поднимается 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, строка автоматически повышается до ASCII-8BIT.

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

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

строка <=> другая_строка → -1, 0, 1 или 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
строка == объект → true или 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.==.

Также алиас: ===
строка === объект → true или 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.==.

Псевдоним для: ==
строка =~ регулярное_выражение → целое число или nil
строка =~ объект → целое число или 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"
строка[индекс] → новая_строка или nil
строка[начало, длина] → новая_строка или nil
строка[диапазон] → новая_строка или nil
строка[регулярное_выражение, захват = 0] → новая_строка или nil
строка[подстрока] → новая_строка или 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
END_OF_DOCUMENT_MARKER
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. Смотрите String Slices.

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

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

В обоих случаях выше, отсчитывается от конца self, если index отрицателен:

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
Source
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
Source
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; см. Case Mapping.

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

capitalize!(*options) → self or nil
Source
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; см. Case Mapping.

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

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

См. Case Mapping.

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

casecmp?(other_string) → true, false, or nil
Source
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

См. Case Mapping.

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

center(size, pad_string = ' ') → new_string
Source
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
Source
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
Source
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
Source
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
Source
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) очень слабо. Согласно его man-странице, традиционный вывод криптографической функции crypt(3) на Linux имеет всего 2^56 вариаций; сегодня это слишком легко взломать. И это поведение по умолчанию.

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

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

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

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

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

Если по какой-то причине вы не можете перейти на другие современные безопасные алгоритмы хеширования паролей, установите gem `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 в противном случае.

END_OF_DOCUMENT_MARKER
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; см. Case Mapping.

Связанные методы: 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; см. Case Mapping.

Связанные методы: 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 Grapheme Cluster Boundaries); возвращает 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 или 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) → целое число или nil
index(regexp, offset = 0) → целое число или 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
Исходный код
Также алиасируется как: заменить
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.

Если целое Integer index положительное, вставляет other_string в смещение index:

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

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

'foo'.insert(-2, 'bar') # => "fobaro"
inspect → строка
Исходный код
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, заключённый в двойные кавычки, со специальными символами, экранированными:

s = "foo\tbar\tbaz\n"
s.inspect
# => "\"foo\\tbar\\tbaz\\n\""
intern → символ
Исходный код
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 → целое число
Исходный код
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
Также алиасируется как: размер
lines(Line_sep = $/, chomp: false) → массив_строк
Исходный код
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 или 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!.

END_OF_DOCUMENT_MARKER
match(pattern, offset = 0) → matchdata or nil
match(pattern, offset = 0) {|matchdata| ... } → object
Source
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
Source
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
Alias for: succ
next!
Alias for: succ!
oct → integer
Source
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
Source
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]
Source
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));
}

Возвращает 3-элементный массив подстрок self.

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

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

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

Если шаблон найден, возвращает pre-match, first-match, post-match:

'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
Source
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"
Alias for: initialize_copy
reverse → string
Source
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
Source
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
Source
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));
}

Возвращает 3-элементный массив подстрок 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);
}

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

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

См. 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 или nil
slice!(start, length) → new_string или nil
slice!(range) → new_string или nil
slice!(regexp, capture = 0) → new_string или nil
slice!(substring) → new_string или 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 Slices.

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

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) → массив
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))

    beg = 0;
    char *ptr = RSTRING_PTR(str);
    char *eptr = RSTRING_END(str);
    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 *str_start = ptr;
        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);
            ptr += end + slen;
            substr_start = ptr;
            if (!NIL_P(limit) && lim <= ++i) break;
        }
        beg = ptr - str_start;
    }
    else if (split_type == SPLIT_TYPE_CHARS) {
        char *str_start = ptr;
        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, «сжатыми» (см. Multiple Character 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 или 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 или 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 in Strings:

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 или 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 если изменения были внесены, 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.

См. Substitution Methods.

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

sub!(pattern, replacement) → self или nil
sub!(pattern) {|match| ... } → self или 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) → целое число
Исходный код
static VALUE
rb_str_sum(int argc, VALUE *argv, VALUE str)
{
    int bits = 16;
    char *ptr, *p, *pend;
    long len;
    VALUE sum = INT2FIX(0);
    unsigned long sum0 = 0;

    if (rb_check_arity(argc, 0, 1) && (bits = NUM2INT(argv[0])) < 0) {
        bits = 0;
    }
    ptr = p = RSTRING_PTR(str);
    len = RSTRING_LEN(str);
    pend = p + len;

    while (p < pend) {
        if (FIXNUM_MAX - UCHAR_MAX < sum0) {
            sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
            str_mod_check(str, ptr, len);
            sum0 = 0;
        }
        sum0 += (unsigned char)*p;
        p++;
    }

    if (bits == 0) {
        if (sum0) {
            sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
        }
    }
    else {
        if (sum == INT2FIX(0)) {
            if (bits < (int)sizeof(long)*CHAR_BIT) {
                sum0 &= (((unsigned long)1)<<bits)-1;
            }
            sum = LONG2FIX(sum0);
        }
        else {
            VALUE mod;

            if (sum0) {
                sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
            }

            mod = rb_funcall(INT2FIX(1), idLTLT, 1, INT2FIX(bits));
            mod = rb_funcall(mod, '-', 1, INT2FIX(1));
            sum = rb_funcall(sum, '&', 1, mod);
        }
    }
    return sum;
}

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

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

Это не особенно сильная контрольная сумма.

swapcase(*options) → строка
Исходный код
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 или 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 → комплексное
Исходный код
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)

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

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

См. Kernel#Complex.

to_f → вещественное
Исходный код
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) → целое число
Исходный код
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 → рациональное
Исходный код
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 или строка
Исходный код
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, соответствующий 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 или 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) → строка
Исходный код
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 или 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 → строка
Исходный код
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) → строка
Исходный код
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 или 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) → массив
Исходный код
# 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) → объект
Исходный код
# File pack.rb, line 33
def unpack1(fmt, offset: 0)
  Primitive.pack_unpack1(fmt, offset)
end

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

upcase(*options) → строка
Исходный код
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 или 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 или 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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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