class String

Overview

AString represents an immutable sequence of UTF-8 characters.

AString is typically created with a string literal, enclosing UTF-8 characters in double quotes:

"hello world"

SeeString literals in the language reference.

A backslash can be used to denote some characters inside the string:

"\"" # double quote
"\\" # backslash
"\e" # escape
"\f" # form feed
"\n" # newline
"\r" # carriage return
"\t" # tab
"\v" # vertical tab

You can use a backslash followed by anu and four hexadecimal characters to denote a unicode codepoint written:

"\u0041" # == "A"

Or you can use curly braces and specify up to six hexadecimal numbers (0 to 10FFFF):

"\u{41}" # == "A"

A string can span multiple lines:

"hello
      world" # same as "hello\n      world"

Note that in the above example trailing and leading spaces, as well as newlines, end up in the resulting string. To avoid this, you can split a string into multiple lines by joining multiple literals with a backslash:

"hello " \
"world, " \
"no newlines" # same as "hello world, no newlines"

Alternatively, a backslash followed by a newline can be inserted inside the string literal:

"hello \
     world, \
     no newlines" # same as "hello world, no newlines"

In this case, leading whitespace is not included in the resulting string.

If you need to write a string that has many double quotes, parentheses, or similar characters, you can use alternative literals:

# Supports double quotes and nested parentheses
%(hello ("world")) # same as "hello (\"world\")"

# Supports double quotes and nested brackets
%[hello ["world"]] # same as "hello [\"world\"]"

# Supports double quotes and nested curlies
%{hello {"world"}} # same as "hello {\"world\"}"

# Supports double quotes and nested angles
%<hello <"world">> # same as "hello <\"world\">"

To create aString with embedded expressions, you can use string interpolation:

a = 1
b = 2
"sum = #{a + b}" # "sum = 3"

This ends up invokingObject#to_s(IO) on each expression enclosed by#{...}.

If you need to dynamically build a string, useString#build orIO::Memory.

Non UTF-8 valid strings

A string might end up being composed of bytes which form an invalid byte sequence according to UTF-8. This can happen if the string is created via one of the constructors that accept bytes, or when getting a string fromString.build orIO::Memory. No exception will be raised, but every byte that doesn't start a valid UTF-8 byte sequence is interpreted as though it encodes the Unicode replacement character (U+FFFD) by itself. For example:

# here 255 is not a valid byte value in the UTF-8 encoding
string = String.new(Bytes[255, 97])
string.valid_encoding? # => false

# The first char here is the unicode replacement char
string.chars # => ['�', 'a']

One can also create strings with specific byte value in them by using octal and hexadecimal escape sequences:

# Octal escape sequences
"\101" # # => "A"
"\12"  # # => "\n"
"\1"   # string with one character with code point 1
"\377" # string with one byte with value 255

# Hexadecimal escape sequences
"\x41" # # => "A"
"\xFF" # string with one byte with value 255

The reason for allowing strings that don't have a valid UTF-8 sequence is that the world is full of content that isn't properly encoded, and having a program raise an exception or stop because of this is not good. It's better if programs are more resilient, but show a replacement character when there's an error in incoming data.

Note that this interpretation only applies to methods inside Crystal; calling #to_slice or#to_unsafe, e.g. when passing a string to a C library, will expose the invalid UTF-8 byte sequences. In particular,Regex's underlying engine may reject strings that are not valid UTF-8, or it may invoke undefined behavior on invalid strings. If this is undesired,#scrub could be used to remove the offending byte sequences first.

Included Modules

Defined in:

big/big_decimal.cr
big/big_float.cr
big/big_int.cr
json/to_json.cr
log/metadata.cr
string.cr
string/grapheme.cr
string/grapheme/grapheme.cr
string/utf16.cr
uri/params/to_www_form.cr
yaml/to_yaml.cr

Constructors

Class Method Summary

Instance Method Summary

Instance methods inherited from module Comparable(String)

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range)
clamp

Instance methods inherited from class Reference

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other)
==
, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil)
same?
, to_s(io : IO) : Nil to_s

Constructor methods inherited from class Reference

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

Class methods inherited from class Reference

pre_initialize(address : Pointer) pre_initialize

Instance methods inherited from class Object

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other)
===
, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash
hash
, in?(collection : Object) : Bool
in?(*values : Object) : Bool
in?
, inspect(io : IO) : Nil
inspect : String
inspect
, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil!
not_nil!
, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String
to_json
, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil
to_pretty_json
, to_s(io : IO) : Nil
to_s : String
to_s
, to_yaml(io : IO) : Nil
to_yaml : String
to_yaml
, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

Class methods inherited from class Object

from_json(string_or_io : String | IO, root : String)
from_json(string_or_io : String | IO)
from_json
, from_yaml(string_or_io : String | IO) from_yaml

Macros inherited from class Object

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

Constructor Detail

def self.additive_identity : String #

Returns the empty string.


def self.build(capacity = 64, &) : self #

Builds aString by creating aString::Builder with the given initial capacity, yielding it to the block and finally getting aString out of it. TheString::Builder automatically resizes as needed.

str = String.build do |str|
  str << "hello "
  str << 1
end
str # => "hello 1"

def self.from_json_object_key?(key : String) : String #

def self.from_utf16(slice : Slice(UInt16), *, truncate_at_null : Bool = false) : String #

Decodes the givenslice UTF-16 sequence into a String.

Invalid values are encoded using the unicode replacement char with codepoint0xfffd.

Iftruncate_at_null is true, only the characters up to and not including the first null character are copied.

slice = Slice[104_u16, 105_u16, 32_u16, 55296_u16, 56485_u16]
String.from_utf16(slice) # => "hi 𐂥"

slice = UInt16.slice(102, 111, 111, 0, 98, 97, 114)
String.from_utf16(slice, truncate_at_null: true) # => "foo"

def self.interpolation(value : String, char : Char) : String #

Implementation of string interpolation of a string and a char.

For example, this code will end up invoking this method:

char = '!'
"hello#{char}" # same as String.interpolation("hello", char)

In this case the implementation just doesvalue + char.

NOTE there should never be a need to call this method instead of using string interpolation.


def self.interpolation(char : Char, value : String) : String #

Implementation of string interpolation of a char and a string.

For example, this code will end up invoking this method:

char = '!'
"#{char}hello" # same as String.interpolation(char, "hello")

In this case the implementation just doeschar + value.

NOTE there should never be a need to call this method instead of using string interpolation.


def self.interpolation(value : String) : String #

Implementation of string interpolation of a single string.

For example, this code will end up invoking this method:

value = "hello"
"#{value}" # same as String.interpolation(value)

In this case the implementation just returns the same string.

NOTE there should never be a need to call this method instead of using string interpolation.


def self.interpolation(value) : String #

Implementation of string interpolation of a single non-string value.

For example, this code will end up invoking this method:

value = 123
"#{value}" # same as String.interpolation(value)

In this case the implementation just returns the result of callingvalue.to_s.

NOTE there should never be a need to call this method instead of using string interpolation.


def self.interpolation(*values : String) : String #

Implementation of string interpolation of multiple string values.

For example, this code will end up invoking this method:

value1 = "hello"
value2 = "world"
"#{value1} #{value2}!" # same as String.interpolation(value1, " ", value2, "!")

In this case the implementation can pre-compute the needed string bytesize and so it's a bit more performant than interpolating non-string values.

NOTE there should never be a need to call this method instead of using string interpolation.


def self.interpolation(*values : *T) : String forall T #

Implementation of string interpolation of multiple, possibly non-string values.

For example, this code will end up invoking this method:

value1 = "hello"
value2 = 123
"#{value1} #{value2}!" # same as String.interpolation(value1, " ", value2, "!")

In this case the implementation will callString.build with the given values.

NOTE there should never be a need to call this method instead of using string interpolation.


def self.new(bytes : Bytes, encoding : String, invalid : Symbol | Nil = nil) : String #

Creates a newString from the givenbytes, which are encoded in the givenencoding.

Theinvalid argument can be:

  • nil: an exception is raised on invalid byte sequences
  • :skip: invalid byte sequences are ignored
slice = Slice.new(2, 0_u8)
slice[0] = 186_u8
slice[1] = 195_u8
String.new(slice, "GB2312") # => "好"

def self.new(chars : Pointer(UInt8), bytesize, size = 0) #

Creates a newString from a pointer, indicating its bytesize count and, optionally, the UTF-8 codepoints count (size).Bytes will be copied from the pointer.

If the given size is zero, the amount of UTF-8 codepoints will be lazily computed when needed.

ptr = Pointer.malloc(4) { |i| ('a'.ord + i).to_u8 }
String.new(ptr, 2) # => "ab"

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #

def self.new(chars : Pointer(UInt8)) #

Creates aString from a pointer.Bytes will be copied from the pointer.

This method isunsafe: the pointer must point to data that eventually contains a zero byte that indicates the ends of the string. Otherwise, the result of this method is undefined and might cause a segmentation fault.

This method is typically used in C bindings, where you get achar* from a library and the library guarantees that this pointer eventually has an ending zero byte.

ptr = Pointer.malloc(5) { |i| i == 4 ? 0_u8 : ('a'.ord + i).to_u8 }
String.new(ptr) # => "abcd"

def self.new(pull : JSON::PullParser) : self #

def self.new(slice : Bytes, *, truncate_at_null : Bool = false) #

Creates aString from the givenslice.Bytes will be copied from the slice.

This method is always safe to call, and the resulting string will have the contents and size of the slice.

Iftruncate_at_null is true, only the characters up to and not including the first null character are copied.

slice = Slice.new(4) { |i| ('a'.ord + i).to_u8 }
String.new(slice) # => "abcd"

slice = UInt8.slice(102, 111, 111, 0, 98, 97, 114)
String.new(slice, truncate_at_null: true) # => "foo"

def self.new(capacity : Int, &) #

Creates a newString by allocating a buffer (Pointer(UInt8)) with the given capacity, then yielding that buffer. The block must return a tuple with the bytesize and size (UTF-8 codepoints count) of the String. If the returned size is zero, the UTF-8 codepoints count will be lazily computed.

The bytesize returned by the block must be less than or equal to the capacity given to this String, otherwiseArgumentError is raised.

If you need to build aString where the maximum capacity is unknown, useString#build.

str = String.new(4) do |buffer|
  buffer[0] = 'a'.ord.to_u8
  buffer[1] = 'b'.ord.to_u8
  {2, 2}
end
str # => "ab"

Class Method Detail

def self.from_utf16(pointer : Pointer(UInt16)) : Tuple(String, Pointer(UInt16)) #

Decodes the givenslice UTF-16 sequence into a String and returns the pointer after reading. The string ends when a zero value is found.

slice = Slice[104_u16, 105_u16, 0_u16, 55296_u16, 56485_u16, 0_u16]
String.from_utf16(slice) # => "hi\0000𐂥\u0000"
pointer = slice.to_unsafe
string, pointer = String.from_utf16(pointer)
string # => "hi"
string, pointer = String.from_utf16(pointer)
string # => "𐂥"

Invalid values are encoded using the unicode replacement char with codepoint0xfffd.


Instance Method Detail

def %(other) : String #

Interpolatesother into the string using top-level::sprintf.

"I have %d apples" % 5                                             # => "I have 5 apples"
"%s, %s, %s, D" % ['A', 'B', 'C']                                  # => "A, B, C, D"
"sum: %{one} + %{two} = %{three}" % {one: 1, two: 2, three: 1 + 2} # => "sum: 1 + 2 = 3"
"I have %<apples>s apples" % {apples: 4}                           # => "I have 4 apples"

def *(times : Int) : String #

Makes a newString by addingstr to itselftimes times.

"Developers! " * 4
# => "Developers! Developers! Developers! Developers! "

def +(other : self) : String #

Concatenatesstr andother.

"abc" + "def" # => "abcdef"
"abc" + 'd'   # => "abcd"

def +(char : Char) : String #

Concatenatesstr andother.

"abc" + "def" # => "abcdef"
"abc" + 'd'   # => "abcd"

def <=>(other : self) : Int32 #

The comparison operator.

Compares this string withother, returning-1,0 or1 depending on whether this string is less, equal or greater thanother.

Comparison is done byte-per-byte: if a byte is less than the other corresponding byte,-1 is returned and so on. This means two strings containing invalid UTF-8 byte sequences may compare unequal, even when they both produce the Unicode replacement character at the same string indices.

If the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered greater than the shorter one.

"abcdef" <=> "abcde"   # => 1
"abcdef" <=> "abcdef"  # => 0
"abcdef" <=> "abcdefg" # => -1
"abcdef" <=> "ABCDEF"  # => 1

The comparison is case-sensitive.#compare is a case-insensitive alternative.


def ==(other : self) : Bool #

Returnstrue if this string is equal to`other.

Equality is checked byte-per-byte: if any byte is different from the corresponding byte, it returnsfalse. This means two strings containing invalid UTF-8 byte sequences may compare unequal, even when they both produce the Unicode replacement character at the same string indices.

Thus equality is case-sensitive, as it is with the comparison operator (#<=>). #compare offers a case-insensitive alternative.

"abcdef" == "abcde"   # => false
"abcdef" == "abcdef"  # => true
"abcdef" == "abcdefg" # => false
"abcdef" == "ABCDEF"  # => false

"abcdef".compare("ABCDEF", case_insensitive: true) == 0 # => true

def ==(other : Log::Metadata::Value) #

def =~(regex : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Int32 | Nil #

Tests whetherstr matchesregex. If successful, it returns the position of the first match. If unsuccessful, it returnsnil.

If the argument isn't aRegex, it returnsnil.

"Haystack" =~ /ay/ # => 1
"Haystack" =~ /z/  # => nil

"Haystack" =~ 45 # => nil

def =~(other, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Nil #

Tests whetherstr matchesregex. If successful, it returns the position of the first match. If unsuccessful, it returnsnil.

If the argument isn't aRegex, it returnsnil.

"Haystack" =~ /ay/ # => 1
"Haystack" =~ /z/  # => nil

"Haystack" =~ 45 # => nil

def [](start : Int, count : Int) : String #

Returns a substring starting from thestart character of sizecount.

Negativestart is added toself.size, thus it's treated as a character index counting from the end,-1 designating the last character.

RaisesIndexError ifstart index is out of bounds. RaisesArgumentError ifcount is negative.


def [](regex : Regex, group, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

def [](index : Int) : Char #

Returns theChar at the givenindex.

Negative indices can be used to start counting from the end of the string.

RaisesIndexError if theindex is out of bounds.

"hello"[0]  # => 'h'
"hello"[1]  # => 'e'
"hello"[-1] # => 'o'
"hello"[-2] # => 'l'
"hello"[5]  # raises IndexError

def [](range : Range) : String #

Returns the substring indicated byrange as span of character indices.

The substring ranges fromself[range.begin] toself[range.end] (orself[range.end - 1] if the range is exclusive). It can be smaller than range.size if the end index is larger thanself.size.

s = "abcde"
s[1..3] # => "bcd"
# range.end > s.size
s[3..7] # => "de"

Open ended ranges are clamped at the start and end ofself, respectively.

# open ended ranges
s[2..] # => "cde"
s[..2] # => "abc"

Negative range values are added toself.size, thus they are treated as character indices counting from the end,-1 designating the last character.

# negative indices, both ranges are equivalent for `s`
s[1..3]   # => "bcd"
s[-4..-2] # => "bcd"
# Mixing negative and positive indices, both ranges are equivalent for `s`
s[1..-2] # => "bcd"
s[-4..3] # => "bcd"

RaisesIndexError if the start index it out of range (range.begin > self.size || range.begin < -self.size). If range.begin == self.sizean empty string is returned. Ifrange.begin &gt; range.end`, an empty string is returned.

# range.begin > array.size
s[6..10] # raise IndexError
# range.begin == s.size
s[5..10] # => ""
# range.begin > range.end
s[3..1]   # => ""
s[-2..-4] # => ""
s[-2..1]  # => ""
s[3..-4]  # => ""

def [](str : String | Char) #

Returnsstr ifstr is found in this string.

"crystal"["cry"]  # => "cry"
"crystal"["ruby"] # raises NilAssertionError

def [](regex : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

def []?(start : Int, count : Int) : String | Nil #

Like#[](Int, Int) but returnsnil if thestart index is out of bounds.


def []?(regex : Regex, group, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String | Nil #

def []?(range : Range) : String | Nil #

Like#[](Range), but returnsnil ifrange.begin is out of range.

"hello"[6..7]? # => nil
"hello"[6..]?  # => nil

def []?(index : Int) : Char | Nil #

Returns the character atindex ornil if it's out of range.

Negative indices can be used to start counting from the end of the string.

See#[] for a raising alternative.

"hello"[0]?  # => 'h'
"hello"[1]?  # => 'e'
"hello"[-1]? # => 'o'
"hello"[-2]? # => 'l'
"hello"[5]?  # => nil

def []?(str : String | Char) #

Returnsstr ifstr is found in this string, ornil otherwise.

"crystal"["cry"]?  # => "cry"
"crystal"["ruby"]? # => nil

def []?(regex : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String | Nil #

def ascii_only? : Bool #

Returnstrue if this String is comprised in its entirety by ASCII characters.

"hello".ascii_only? # => true
"你好".ascii_only?    # => false

def blank? : Bool #

Returnstrue if this string consists exclusively of unicode whitespace.

"".blank?        # => true
"   ".blank?     # => true
"   a   ".blank? # => false

def byte_at(index) : UInt8 #

Returns the byte at the givenindex.

RaisesIndexError if theindex is out of bounds.

"¥hello".byte_at(0)  # => 194
"¥hello".byte_at(1)  # => 165
"¥hello".byte_at(2)  # => 104
"¥hello".byte_at(-1) # => 111
"¥hello".byte_at(6)  # => 111
"¥hello".byte_at(7)  # raises IndexError

def byte_at(index, &) #

Returns the byte at the givenindex, or yields if out of bounds.

"¥hello".byte_at(6) { "OUT OF BOUNDS" } # => 111
"¥hello".byte_at(7) { "OUT OF BOUNDS" } # => "OUT OF BOUNDS"

def byte_at?(index) : UInt8 | Nil #

Returns the byte at the givenindex, ornil if out of bounds.

"¥hello".byte_at?(0)  # => 194
"¥hello".byte_at?(1)  # => 165
"¥hello".byte_at?(2)  # => 104
"¥hello".byte_at?(-1) # => 111
"¥hello".byte_at?(6)  # => 111
"¥hello".byte_at?(7)  # => nil

def byte_index(byte : Int, offset : Int32 = 0) : Int32 | Nil #

Returns the index of thefirst occurrence ofbyte in the string, ornil if not present. Ifoffset is present, it defines the position to start the search.

Negativeoffset can be used to start the search from the end of the string.

"Hello, World".byte_index(0x6f)             # => 4
"Hello, World".byte_index(0x5a)             # => nil
"Hello, World".byte_index(0x6f, 5)          # => 8
"💣".byte_index(0xA3)                        # => 3
"Dizzy Miss Lizzy".byte_index('z'.ord)      # => 2
"Dizzy Miss Lizzy".byte_index('z'.ord, 3)   # => 3
"Dizzy Miss Lizzy".byte_index('z'.ord, -4)  # => 13
"Dizzy Miss Lizzy".byte_index('z'.ord, -17) # => nil

def byte_index(char : Char, offset = 0) : Int32 | Nil #

Returns the index of thefirst occurrence ofchar in the string, ornil if not present. Ifoffset is present, it defines the position to start the search.

Negativeoffset can be used to start the search from the end of the string.

"Hello, World".byte_index('o')          # => 4
"Hello, World".byte_index('Z')          # => nil
"Hello, World".byte_index('o', 5)       # => 8
"Hi, 💣".byte_index('💣')                 # => 4
"Dizzy Miss Lizzy".byte_index('z')      # => 2
"Dizzy Miss Lizzy".byte_index('z', 3)   # => 3
"Dizzy Miss Lizzy".byte_index('z', -4)  # => 13
"Dizzy Miss Lizzy".byte_index('z', -17) # => nil

def byte_index(search : String, offset = 0) : Int32 | Nil #

Returns the byte index ofsearch in the string, ornil if the string is not present. Ifoffset is present, it defines the position to start the search.

Negativeoffset can be used to start the search from the end of the string.

"¥hello".byte_index("hello")              # => 2
"hello".byte_index("world")               # => nil
"Dizzy Miss Lizzy".byte_index("izzy")     # => 1
"Dizzy Miss Lizzy".byte_index("izzy", 2)  # => 12
"Dizzy Miss Lizzy".byte_index("izzy", -4) # => 12
"Dizzy Miss Lizzy".byte_index("izzy", -3) # => nil

def byte_index(pattern : Regex, offset = 0, options : Regex::MatchOptions = Regex::MatchOptions::None) : Int32 | Nil #

Returns the byte index of the regexpattern in the string, ornil if the pattern does not find a match. Ifoffset is present, it defines the position to start the search.

Negativeoffset can be used to start the search from the end of the string.

"hello world".byte_index(/o/)             # => 4
"hello world".byte_index(/o/, offset: 4)  # => 4
"hello world".byte_index(/o/, offset: 5)  # => 7
"hello world".byte_index(/o/, offset: -1) # => nil
"hello world".byte_index(/y/)             # => nil

def byte_index_to_char_index(index) : Int32 | Nil #

Returns the char index of a byte index, ornil if out of bounds.

It is valid to pass#bytesize toindex, and in this case the answer will be the size of this string.


def byte_slice(start : Int, count : Int) : String #

Returns a new string built fromcount bytes starting atstart byte.

start can be negative to start counting from the end of the string. Ifcount is bigger than the number of bytes fromstart to#bytesize, only remaining bytes are returned.

This method should be avoided, unless the string is proven to be ASCII-only (for example#ascii_only?), or the byte positions are known to be at character boundaries. Otherwise, multi-byte characters may be split, leading to an invalid UTF-8 encoding.

RaisesIndexError if thestart index is out of bounds.

RaisesArgumentError ifcount is negative.

"hello".byte_slice(0, 2)   # => "he"
"hello".byte_slice(0, 100) # => "hello"
"hello".byte_slice(-2, 3)  # => "lo"
"hello".byte_slice(-2, 5)  # => "lo"
"¥hello".byte_slice(0, 2)  # => "¥"
"¥hello".byte_slice(2, 2)  # => "he"
"¥hello".byte_slice(0, 1)  # => "\xC2" (invalid UTF-8 character)
"¥hello".byte_slice(1, 1)  # => "\xA5" (invalid UTF-8 character)
"¥hello".byte_slice(1, 2)  # => "\xA5h" (invalid UTF-8 character)
"hello".byte_slice(6, 2)   # raises IndexError
"hello".byte_slice(-6, 2)  # raises IndexError
"hello".byte_slice(0, -2)  # raises ArgumentError

def byte_slice(range : Range) : String #

Returns a new string built from byte inrange.

Byte indices can be negative to start counting from the end of the string. If the end index is bigger than#bytesize, only remaining bytes are returned.

This method should be avoided, unless the string is proven to be ASCII-only (for example#ascii_only?), or the byte positions are known to be at character boundaries. Otherwise, multi-byte characters may be split, leading to an invalid UTF-8 encoding.

RaisesIndexError if therange begin is out of bounds.

"hello".byte_slice(0..2)   # => "hel"
"hello".byte_slice(0..100) # => "hello"
"hello".byte_slice(-2..3)  # => "l"
"hello".byte_slice(-2..5)  # => "lo"
"¥hello".byte_slice(0...2) # => "¥"
"¥hello".byte_slice(2...4) # => "he"
"¥hello".byte_slice(0..0)  # => "\xC2" (invalid UTF-8 character)
"¥hello".byte_slice(1..1)  # => "\xA5" (invalid UTF-8 character)
"¥hello".byte_slice(1..2)  # => "\xA5h" (invalid UTF-8 character)
"hello".byte_slice(6..2)   # raises IndexError
"hello".byte_slice(-6..2)  # raises IndexError

def byte_slice(start : Int) : String #

Returns a substring starting from thestart byte.

start can be negative to start counting from the end of the string.

This method should be avoided, unless the string is proven to be ASCII-only (for example#ascii_only?), or the byte positions are known to be at character boundaries. Otherwise, multi-byte characters may be split, leading to an invalid UTF-8 encoding.

RaisesIndexError ifstart index is out of bounds.

"hello".byte_slice(0)  # => "hello"
"hello".byte_slice(2)  # => "llo"
"hello".byte_slice(-2) # => "lo"
"¥hello".byte_slice(2) # => "hello"
"¥hello".byte_slice(1) # => "\xA5hello" (invalid UTF-8 character)
"hello".byte_slice(6)  # raises IndexError
"hello".byte_slice(-6) # raises IndexError

def byte_slice?(start : Int, count : Int) : String | Nil #

Like#byte_slice(Int, Int) but returnsNil if thestart index is out of bounds.

RaisesArgumentError ifcount is negative.

"hello".byte_slice?(0, 2)   # => "he"
"hello".byte_slice?(0, 100) # => "hello"
"hello".byte_slice?(6, 2)   # => nil
"hello".byte_slice?(-6, 2)  # => nil
"hello".byte_slice?(0, -2)  # raises ArgumentError

def byte_slice?(range : Range) : String | Nil #

Like#byte_slice(Range) but returnsNil ifrange begin is out of bounds.

"hello".byte_slice?(0..2)   # => "hel"
"hello".byte_slice?(0..100) # => "hello"
"hello".byte_slice?(6..8)   # => nil
"hello".byte_slice?(-6..2)  # => nil

def byte_slice?(start : Int) : String | Nil #

Returns a substring starting from thestart byte.

start can be negative to start counting from the end of the string.

This method should be avoided, unless the string is proven to be ASCII-only (for example#ascii_only?), or the byte positions are known to be at character boundaries. Otherwise, multi-byte characters may be split, leading to an invalid UTF-8 encoding.

Returnsnil ifstart index is out of bounds.

"hello".byte_slice?(0)  # => "hello"
"hello".byte_slice?(2)  # => "llo"
"hello".byte_slice?(-2) # => "lo"
"¥hello".byte_slice?(2) # => "hello"
"¥hello".byte_slice?(1) # => "\xA5hello" (invalid UTF-8 character)
"hello".byte_slice?(6)  # => nil
"hello".byte_slice?(-6) # => nil

def bytes : Array(UInt8) #

Returns this string's bytes as anArray(UInt8).

"hello".bytes # => [104, 101, 108, 108, 111]
"你好".bytes    # => [228, 189, 160, 229, 165, 189]

def bytesize : Int32 #

Returns the number of bytes in this string.

"hello".bytesize # => 5
"你好".bytesize    # => 6

def camelcase(io : IO, options : Unicode::CaseOptions = Unicode::CaseOptions::None, *, lower : Bool = false) : Nil #

Writes an camelcased version ofself to the givenio.

Iflower is true, lower camelcase will be written (the first letter is downcased).

io = IO::Memory.new
"eiffel_tower".camelcase io
io.to_s # => "EiffelTower"

def camelcase(options : Unicode::CaseOptions = Unicode::CaseOptions::None, *, lower : Bool = false) : String #

Converts underscores to camelcase boundaries.

Iflower is true, lower camelcase will be returned (the first letter is downcased).

"eiffel_tower".camelcase                                            # => "EiffelTower"
"empire_state_building".camelcase(lower: true)                      # => "empireStateBuilding"
"isolated_integer".camelcase(options: Unicode::CaseOptions::Turkic) # => "İsolatedİnteger"

def capitalize(options : Unicode::CaseOptions = :none) : String #

Returns a newString with the first letter converted to uppercase and every subsequent letter converted to lowercase.

"hEllO".capitalize # => "Hello"

def capitalize(io : IO, options : Unicode::CaseOptions = :none) : Nil #

Writes a capitalized version ofself to the givenio.

io = IO::Memory.new
"hEllO".capitalize io
io.to_s # => "Hello"

def center(len : Int, char : Char = ' ') : String #

Adds instances ofchar to left and right of the string until it is at least size oflen.

"Purple".center(8)      # => " Purple "
"Purple".center(8, '-') # => "-Purple-"
"Purple".center(9, '-') # => "-Purple--"
"Aubergine".center(8)   # => "Aubergine"

def center(io : IO, len : Int, char : Char = ' ') : Nil #

Adds instances ofchar to left and right of the string until it is at least size oflen, then appends the result to the given IO.

io = IO::Memory.new
"Purple".center(io, 9, '-')
io.to_s # => "-Purple--"

def char_at(index : Int) : Char #

Returns theChar at the givenindex.

Negative indices can be used to start counting from the end of the string.

RaisesIndexError if theindex is out of bounds.

"hello".char_at(0)  # => 'h'
"hello".char_at(1)  # => 'e'
"hello".char_at(-1) # => 'o'
"hello".char_at(-2) # => 'l'
"hello".char_at(5)  # raises IndexError

def char_at(index : Int, &) #

Returns theChar at the givenindex, or result of running the given block if out of bounds.

Negative indices can be used to start counting from the end of the string.

"hello".char_at(4) { 'x' }  # => 'o'
"hello".char_at(5) { 'x' }  # => 'x'
"hello".char_at(-1) { 'x' } # => 'o'
"hello".char_at(-5) { 'x' } # => 'h'
"hello".char_at(-6) { 'x' } # => 'x'

def char_index_to_byte_index(index) #

Returns the byte index of a char index, ornil if out of bounds.

It is valid to pass#size toindex, and in this case the answer will be the bytesize of this string.

"hello".char_index_to_byte_index(1) # => 1
"hello".char_index_to_byte_index(5) # => 5
"こんにちは".char_index_to_byte_index(1) # => 3
"こんにちは".char_index_to_byte_index(5) # => 15

def chars : Array(Char) #

Returns anArray of all characters in the string.

"ab☃".chars # => ['a', 'b', '☃']

def check_no_null_byte(name = nil) : self #

Raises anArgumentError ifself has null bytes. Returnsself otherwise.

This method should sometimes be called before passing aString to a C function.


def chomp(suffix : Char) : String #

Returns a newString withsuffix removed from the end of the string. Ifsuffix is'\n' then"\r\n" is also removed if the string ends with it.

"hello".chomp('o') # => "hell"
"hello".chomp('a') # => "hello"

def chomp(suffix : String) : String #

Returns a newString withsuffix removed from the end of the string. Ifsuffix is"\n" then"\r\n" is also removed if the string ends with it.

"hello".chomp("llo") # => "he"
"hello".chomp("ol")  # => "hello"

def chomp : String #

Returns a newString with the last carriage return removed (that is, it will remove\n,\r, and\r\n).

"string\r\n".chomp # => "string"
"string\n\r".chomp # => "string\n"
"string\n".chomp   # => "string"
"string".chomp     # => "string"
"x".chomp.chomp    # => "x"

def clone : String #

Returnsself.


def codepoint_at(index) : Int32 #

Returns the codepoint of the character at the givenindex.

Negative indices can be used to start counting from the end of the string.

RaisesIndexError if theindex is out of bounds.

See also:Char#ord.

"hello".codepoint_at(0)  # => 104
"hello".codepoint_at(-1) # => 111
"hello".codepoint_at(5)  # raises IndexError

def codepoints : Array(Int32) #

Returns anArray of the codepoints that make the string.

"ab☃".codepoints # => [97, 98, 9731]

See also:Char#ord.


def compare(other : String, case_insensitive = false, options : Unicode::CaseOptions = :none) : Int32 #

Compares this string withother, returning-1,0 or1 depending on whether this string is less, equal or greater thanother, optionally in acase_insensitive manner.

Case-sensitive comparisons (case_insensitive == false) are equivalent to #<=> and are always done byte-per-byte.

"abcdef".compare("abcde")   # => 1
"abcdef".compare("abcdef")  # => 0
"abcdef".compare("abcdefg") # => -1
"abcdef".compare("ABCDEF")  # => 1

"abcdef".compare("ABCDEF", case_insensitive: true) # => 0
"abcdef".compare("ABCDEG", case_insensitive: true) # => -1

"heIIo".compare("heııo", case_insensitive: true, options: Unicode::CaseOptions::Turkic) # => 0
"Baffle".compare("baffle", case_insensitive: true, options: Unicode::CaseOptions::Fold)   # => 0

Case-sensitive only comparison is provided by the comparison operator#<=>.


def count(&) : Int32 #

Yields each char in this string to the block, returns the number of times the block returned a truthy value.

"aabbcc".count &.in?('a', 'b') # => 4

def count(other : Char) : Int32 #

Counts the occurrences ofother char in this string.

"aabbcc".count('a') # => 2

def count(*sets) : Int32 #

Sets should be a list of strings following the rules described atChar#in_set?. Returns the number of characters in this string that match the given set.


def delete(&) : String #

Yields each char in this string to the block. Returns a newString with all characters for which the block returned a truthy value removed.

"aabbcc".delete &.in?('a', 'b') # => "cc"

def delete(char : Char) : String #

Returns a newString with all occurrences ofchar removed.

"aabbcc".delete('b') # => "aacc"

def delete(*sets) : String #

Sets should be a list of strings following the rules described atChar#in_set?. Returns a newString with all characters that match the given set removed.

"aabbccdd".delete("a-c") # => "dd"

def delete_at(start : Int, count : Int) : String #

Returns a new string that results from deletingcount characters starting atstart.

"abcdefg".delete_at(1, 3) # => "aefg"

Deleting more characters than those in the string is valid, and just results in deleting up to the last character:

"abcdefg".delete_at(3, 10) # => "abc"

A negativestart counts from the end of the string:

"abcdefg".delete_at(-3, 2) # => "abcdg"

Ifcount is negative,ArgumentError is raised.

Ifstart is outside the bounds of the string,ArgumentError is raised.

However,start can be the position that is exactly the end of the string:

"abcd".delete_at(4, 3) # => "abcd"

def delete_at(range : Range) : String #

Returns a new string that results from deleting characters at the given range.

"abcdef".delete_at(1..3) # => "aef"

Negative indices can be used to start counting from the end of the string:

"abcdef".delete_at(-3..-2) # => "abcf"

RaisesIndexError if any index is outside the bounds of this string.


def delete_at(index : Int) : String #

Returns a new string that results from deleting the character at the givenindex.

"abcde".delete_at(0) # => "bcde"
"abcde".delete_at(2) # => "abde"
"abcde".delete_at(4) # => "abcd"

A negativeindex counts from the end of the string:

"abcde".delete_at(-2) # => "abce"

Ifindex is outside the bounds of the string,IndexError is raised.


def delete_at(*, index start : Int, count : Int) : String #

Returns a new string that results from deletingcount characters starting atstart.

"abcdefg".delete_at(1, 3) # => "aefg"

Deleting more characters than those in the string is valid, and just results in deleting up to the last character:

"abcdefg".delete_at(3, 10) # => "abc"

A negativestart counts from the end of the string:

"abcdefg".delete_at(-3, 2) # => "abcdg"

Ifcount is negative,ArgumentError is raised.

Ifstart is outside the bounds of the string,ArgumentError is raised.

However,start can be the position that is exactly the end of the string:

"abcd".delete_at(4, 3) # => "abcd"

DEPRECATED Use#delete_at(start, count) instead


def downcase(options : Unicode::CaseOptions = :none) : String #

Returns a newString with each uppercase letter replaced with its lowercase counterpart.

"hEllO".downcase # => "hello"

def downcase(io : IO, options : Unicode::CaseOptions = :none) : Nil #

Writes a downcased version ofself to the givenio.

io = IO::Memory.new
"hEllO".downcase io
io.to_s # => "hello"

def dump(io : IO) : Nil #

Returns a representation ofself as an ASCII-compatible Crystal string literal, wrapped in double quotes.

Non-printable characters (seeChar#printable?) and non-ASCII characters (codepoints largerU+007F) are escaped.

"\u{1f48e} - à la carte\n".dump # => %("\\u{1F48E} - \\u00E0 la carte\\n")

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def dump : String #

Returns a representation ofself as an ASCII-compatible Crystal string literal, wrapped in double quotes.

Non-printable characters (seeChar#printable?) and non-ASCII characters (codepoints largerU+007F) are escaped.

"\u{1f48e} - à la carte\n".dump # => %("\\u{1F48E} - \\u00E0 la carte\\n")

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def dump_unquoted : String #

Returns a representation ofself as the content of an ASCII-compatible Crystal string literal without delimiters.

Non-printable characters (seeChar#printable?) and non-ASCII characters (codepoints largerU+007F) are escaped.

"\u{1f48e} - à la carte\n".dump_unquoted # => %(\\u{1F48E} - \\u00E0 la carte\\n)

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def dup : String #

Returnsself.


def each_byte(&) #

Yields each byte in the string to the block.

array = [] of UInt8
"ab☃".each_byte do |byte|
  array << byte
end
array # => [97, 98, 226, 152, 131]

def each_byte #

Returns anIterator over each byte in the string.

bytes = "ab☃".each_byte
bytes.next # => 97
bytes.next # => 98
bytes.next # => 226
bytes.next # => 152
bytes.next # => 131

def each_char(&) : Nil #

Yields each character in the string to the block.

array = [] of Char
"ab☃".each_char do |char|
  array << char
end
array # => ['a', 'b', '☃']

def each_char #

Returns anIterator over each character in the string.

chars = "ab☃".each_char
chars.next # => 'a'
chars.next # => 'b'
chars.next # => '☃'

def each_char_with_index(offset = 0, &) #

Yields each character and its index in the string to the block.

array = [] of Tuple(Char, Int32)
"ab☃".each_char_with_index do |char, index|
  array << {char, index}
end
array # => [{'a', 0}, {'b', 1}, {'☃', 2}]

Accepts an optionaloffset parameter, which tells it to start counting from there.


def each_codepoint(&) #

Yields each codepoint to the block.

array = [] of Int32
"ab☃".each_codepoint do |codepoint|
  array << codepoint
end
array # => [97, 98, 9731]

See also:Char#ord.


def each_codepoint #

Returns anIterator for each codepoint.

codepoints = "ab☃".each_codepoint
codepoints.next # => 97
codepoints.next # => 98
codepoints.next # => 9731

See also:Char#ord.


def each_grapheme(& : Grapheme -> _) : Nil #

Yields each Unicode extended grapheme cluster in this string.

Grapheme clusters correspond to&quot;user-perceived characters&quot; and are defined inUnicode Standard Annex #29. A cluster can consist of multiple code points which together form a single glyph.

"a👍🏼à".each_grapheme do |cluster|
  p! cluster
end
  • #graphemes collects all grapheme clusters in an array

EXPERIMENTAL The grapheme API is still under development. Join the discussion at#11610.


def each_grapheme : Iterator(Grapheme) #

Returns an iterator of this string split into Unicode extended grapheme clusters.

Grapheme clusters correspond to&quot;user-perceived characters&quot; and are defined inUnicode Standard Annex #29. A cluster can consist of multiple code points which together form a single glyph.

"a👍🏼à".each_grapheme.to_a # => [String::Grapheme('a'), String::Grapheme("👍🏼"), String::Grapheme("à")]
  • #graphemes collects all grapheme clusters in an array

EXPERIMENTAL The grapheme API is still under development. Join the discussion at#11610.


def each_line(chomp : Bool = true, remove_empty : Bool = false, & : String -> ) : Nil #

Splits the string after each newline and yields each line.

Both LF (line feed,\n) and CRLF (carriage return line feed,\r\n) are recognized as line delimiters.

Ifchomp is true, the line separator is removed from the end of each line.

"hello\nworld".each_line { }                   # yields "hello", "world"
"hello\nworld".each_line(chomp: false) { }     # yields "hello\n", "world"
"hello\nworld\r\n".each_line { }               # yields "hello", "world"
"hello\nworld\r\n".each_line(chomp: false) { } # yields "hello\n", "world\r\n"

Ifremove_empty istrue, any empty lines are removed from the result.

A trailing line feed is not considered starting a final, empty line. The empty string does not contain any lines.

"hello\n".each_line { } # yields "hello"
"\n".each_line { }      # yields ""
"".each_line { }        # does not yield
  • #lines returns an array of lines

def each_line(chomp = true, *, remove_empty : Bool = false) #

Returns anIterator which yields each line of this string (seeString#each_line).


def empty? : Bool #

Returnstrue if this is the empty string,"".


def encode(encoding : String, invalid : Symbol | Nil = nil) : Bytes #

Returns a slice of bytes containing this string encoded in the given encoding.

Theinvalid argument can be:

  • nil: an exception is raised on invalid byte sequences
  • :skip: invalid byte sequences are ignored
"好".encode("GB2312") # => Bytes[186, 195]
"好".bytes            # => [229, 165, 189]

def ends_with?(str : String) : Bool #

Returnstrue if this string ends with the givenstr.

"hello".ends_with?("o")  # => true
"hello".ends_with?("lo") # => true
"hello".ends_with?("ll") # => false

def ends_with?(char : Char) : Bool #

Returnstrue if this string ends with the givenchar.

"hello".ends_with?('o') # => true
"hello".ends_with?('l') # => false

def ends_with?(re : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Bool #

Returnstrue if the regular expressionre matches at the end of this string.

"22hello".ends_with?(/[0-9]/) # => false
"22hello".ends_with?(/[a-z]/) # => true
"22h".ends_with?(/[a-z]/)     # => true
"22h".ends_with?(/[A-Z]/)     # => false
"22h".ends_with?(/[a-z]{2}/)  # => false
"22hh".ends_with?(/[a-z]{2}/) # => true

def ensure_prefix(prefix : String | Char) : self #

Returnsself if it starts with the givenprefix. Otherwise, returns a new String with theprefix prepended.

"llo!".ensure_prefix("He")   # => "Hello!"
"Hello!".ensure_prefix("He") # => "Hello!"
"ello".ensure_prefix('H')    # => "Hello!"
"Hello!".ensure_prefix('H')  # => "Hello!"

def ensure_suffix(suffix : String | Char) : self #

Returnsself if it ends with the givensuffix. Otherwise, returns a new String with thesuffix appended.

"Hell".ensure_suffix("o!")   # => "Hello!"
"Hello!".ensure_suffix("o!") # => "Hello!"
"Hello".ensure_suffix('!')   # => "Hello!"
"Hello!".ensure_suffix('!')  # => "Hello!"

def grapheme_size : Int32 #

Returns the number of Unicode extended graphemes clusters in this string.

EXPERIMENTAL The grapheme API is still under development. Join the discussion at#11610.


def graphemes : Array(Grapheme) #

Returns this string split into Unicode extended grapheme clusters.

Grapheme clusters correspond to&quot;user-perceived characters&quot; and are defined inUnicode Standard Annex #29. A cluster can consist of multiple code points which together form a single glyph.

"a👍🏼à".graphemes # => [String::Grapheme('a'), String::Grapheme("👍🏼"), String::Grapheme("à")]
  • #each_grapheme iterates the grapheme clusters without allocating an array

EXPERIMENTAL The grapheme API is still under development. Join the discussion at#11610.


def gsub(string : String, &) : String #

Returns aString where all occurrences of the givenstring are replaced with the block's value.

"hello yellow".gsub("ll") { "dd" } # => "heddo yeddow"

def gsub(pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None, &) : String #

Returns aString where all occurrences of the givenpattern are replaced by the block value's value.

"hello".gsub(/./) { |s| s[0].ord.to_s + ' ' }                                              # => "104 101 108 108 111 "
"foo bar baz".gsub(/ba./) { |match| match.upcase }                                         # => "foo BAR BAZ"
"Name: Alice, Name: Bob".gsub(/Name: (\w+)/) { |full, matches| "User(#{matches[1]})" }     # => "User(Alice), User(Bob)"
"5x10, 3x7".gsub(/(\d+)x(\d+)/) { |full, matches| "#{matches[1].to_i * matches[2].to_i}" } # => "50, 21"

def gsub(&block : Char -> _) : String #

Returns aString where each character yielded to the given block is replaced by the block's return value.

"hello".gsub { |char| char + 1 } # => "ifmmp"
"hello".gsub { "hi" }            # => "hihihihihi"

def gsub(char : Char, replacement) : String #

Returns aString where all occurrences of the given char are replaced with the givenreplacement.

"hello".gsub('l', "lo")      # => "heloloo"
"hello world".gsub('o', 'a') # => "hella warld"

def gsub(pattern : Regex, hash : Hash(String, _) | NamedTuple, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

Returns aString where all occurrences of the givenpattern are replaced with ahash of replacements. If thehash contains the matched pattern, the corresponding value is used as a replacement. Otherwise the match is not included in the returned string.

# "he" and "l" are matched and replaced,
# but "o" is not and so is not included
"hello".gsub(/(he|l|o)/, {"he": "ha", "l": "la"}) # => "halala"

def gsub(string : String, replacement) : String #

Returns aString where all occurrences of the givenstring are replaced with the givenreplacement.

"hello yellow".gsub("ll", "dd") # => "heddo yeddow"

def gsub(pattern : Regex, replacement, backreferences = true, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

Returns aString where all occurrences of the givenpattern are replaced with the givenreplacement.

"hello".gsub(/[aeiou]/, '*') # => "h*ll*"

Withinreplacement, the special match variable$~ will not refer to the current match.

Ifbackreferences istrue (the default value),replacement can include backreferences:

"hello".gsub(/[aeiou]/, "(\\0)") # => "h(e)ll(o)"

When substitution is performed, any backreferences found inreplacement will be replaced with the contents of the corresponding capture group in pattern. Backreferences to capture groups that were not present in pattern or that did not match will be skipped. SeeRegex for information about capture groups.

Backreferences are expressed in the form"\\d", whered is a group number, or"\\k<name>" wherename is the name of a named capture group. A sequence of literal characters resembling a backreference can be expressed by placing"\\" before the sequence.

"foo".gsub(/o/, "x\\0x")                  # => "fxoxxox"
"foofoo".gsub(/(?<bar>oo)/, "|\\k<bar>|") # => "f|oo|f|oo|"
"foo".gsub(/o/, "\\\\0")                  # => "f\\0\\0"

RaisesArgumentError if an incomplete named back-reference is present in replacement.

RaisesIndexError if a named group referenced inreplacement is not present inpattern.


def gsub(hash : Hash(Char, _)) : String #

Returns aString where all chars in the given hash are replaced by the correspondinghash values.

"hello".gsub({'e' => 'a', 'l' => 'd'}) # => "haddo"

def gsub(tuple : NamedTuple) : String #

Returns aString where all chars in the given named tuple are replaced by the correspondingtuple values.

"hello".gsub({e: 'a', l: 'd'}) # => "haddo"

def has_back_references? #

This returnstrue if this string has'\\' in it. It might not be a back reference, but'\\' is probably used for back references, so this check is faster than parsing the whole thing.


def hash(hasher) #

def hexbytes : Bytes #

Interprets this string as containing a sequence of hexadecimal values and decodes it as a slice of bytes. Two consecutive bytes in the string represent a byte in the returned slice.

RaisesArgumentError if this string does not denote an hexstring.

"0102031aff".hexbytes  # => Bytes[1, 2, 3, 26, 255]
"1".hexbytes           # raises ArgumentError
"hello world".hexbytes # raises ArgumentError

def hexbytes? : Bytes | Nil #

Interprets this string as containing a sequence of hexadecimal values and decodes it as a slice of bytes. Two consecutive bytes in the string represent a byte in the returned slice.

Returnsnil if this string does not denote an hexstring.

"0102031aff".hexbytes?  # => Bytes[1, 2, 3, 26, 255]
"1".hexbytes?           # => nil
"hello world".hexbytes? # => nil

def includes?(search : Char | String) : Bool #

Returnstrue if the string containssearch.

"Team".includes?('i')            # => false
"Dysfunctional".includes?("fun") # => true

def index(search : Char, offset = 0) : Int32 | Nil #

Returns the index of thefirst occurrence ofsearch in the string, ornil if not present. Ifoffset is present, it defines the position to start the search.

"Hello, World".index('o')    # => 4
"Hello, World".index('Z')    # => nil
"Hello, World".index("o", 5) # => 8
"Hello, World".index("H", 2) # => nil
"Hello, World".index(/[ ]+/) # => 6
"Hello, World".index(/\d+/)  # => nil

def index(search : String, offset = 0) #

Returns the index of thefirst occurrence ofsearch in the string, ornil if not present. Ifoffset is present, it defines the position to start the search.

"Hello, World".index('o')    # => 4
"Hello, World".index('Z')    # => nil
"Hello, World".index("o", 5) # => 8
"Hello, World".index("H", 2) # => nil
"Hello, World".index(/[ ]+/) # => 6
"Hello, World".index(/\d+/)  # => nil

def index(search : Regex, offset = 0, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Int32 | Nil #

Returns the index of thefirst occurrence ofsearch in the string, ornil if not present. Ifoffset is present, it defines the position to start the search.

"Hello, World".index('o')    # => 4
"Hello, World".index('Z')    # => nil
"Hello, World".index("o", 5) # => 8
"Hello, World".index("H", 2) # => nil
"Hello, World".index(/[ ]+/) # => 6
"Hello, World".index(/\d+/)  # => nil

def index!(search, offset = 0) : Int32 #

Returns the index of thefirst occurrence ofsearch in the string. Ifoffset is present, it defines the position to start the search.

RaisesEnumerable::NotFoundError ifsearch does not occur inself.

"Hello, World".index!('o')    # => 4
"Hello, World".index!('Z')    # raises Enumerable::NotFoundError
"Hello, World".index!("o", 5) # => 8
"Hello, World".index!("H", 2) # raises Enumerable::NotFoundError
"Hello, World".index!(/[ ]+/) # => 6
"Hello, World".index!(/\d+/)  # raises Enumerable::NotFoundError

def index!(search : Regex, offset = 0, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Int32 #

Returns the index of thefirst occurrence ofsearch in the string. Ifoffset is present, it defines the position to start the search.

RaisesEnumerable::NotFoundError ifsearch does not occur inself.

"Hello, World".index!('o')    # => 4
"Hello, World".index!('Z')    # raises Enumerable::NotFoundError
"Hello, World".index!("o", 5) # => 8
"Hello, World".index!("H", 2) # raises Enumerable::NotFoundError
"Hello, World".index!(/[ ]+/) # => 6
"Hello, World".index!(/\d+/)  # raises Enumerable::NotFoundError

def insert(index : Int, other : Char) : String #

Returns a newString that results of insertingother inself atindex. Negative indices count from the end of the string, and insertafter the given index.

RaisesIndexError if the index is out of bounds.

"abcd".insert(0, 'X')  # => "Xabcd"
"abcd".insert(3, 'X')  # => "abcXd"
"abcd".insert(4, 'X')  # => "abcdX"
"abcd".insert(-3, 'X') # => "abXcd"
"abcd".insert(-1, 'X') # => "abcdX"

"abcd".insert(5, 'X')  # raises IndexError
"abcd".insert(-6, 'X') # raises IndexError

def insert(index : Int, other : String) : String #

Returns a newString that results of insertingother inself atindex. Negative indices count from the end of the string, and insertafter the given index.

RaisesIndexError if the index is out of bounds.

"abcd".insert(0, "FOO")  # => "FOOabcd"
"abcd".insert(3, "FOO")  # => "abcFOOd"
"abcd".insert(4, "FOO")  # => "abcdFOO"
"abcd".insert(-3, "FOO") # => "abFOOcd"
"abcd".insert(-1, "FOO") # => "abcdFOO"

"abcd".insert(5, "FOO")  # raises IndexError
"abcd".insert(-6, "FOO") # raises IndexError

def inspect(io : IO) : Nil #

Returns a representation ofself as a Crystal string literal, wrapped in double quotes.

Non-printable characters (seeChar#printable?) are escaped.

"\u{1f48e} - à la carte\n".inspect # => %("\u{1F48E} - à la carte\\n")

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def inspect : String #

Returns a representation ofself as a Crystal string literal, wrapped in double quotes.

Non-printable characters (seeChar#printable?) are escaped.

"\u{1f48e} - à la carte\n".inspect # => %("\u{1F48E} - à la carte\\n")

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def inspect_unquoted(io : IO) : Nil #

Returns a representation ofself as the content of a Crystal string literal without delimiters.

Non-printable characters (seeChar#printable?) are escaped.

"\u{1f48e} - à la carte\n".inspect_unquoted # => %(\u{1F48E} - à la carte\\n)

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def inspect_unquoted : String #

Returns a representation ofself as the content of a Crystal string literal without delimiters.

Non-printable characters (seeChar#printable?) are escaped.

"\u{1f48e} - à la carte\n".inspect_unquoted # => %(\u{1F48E} - à la carte\\n)

SeeChar#unicode_escape for the format used to escape characters without a special escape sequence.


def lchop(prefix : Char | String) : String #

Returns a newString withprefix removed from the beginning of the string.

"hello".lchop('h')   # => "ello"
"hello".lchop('g')   # => "hello"
"hello".lchop("hel") # => "lo"
"hello".lchop("eh")  # => "hello"

def lchop : String #

Returns a newString with the first char removed from it. Applying lchop to an empty string returns an empty string.

"hello".lchop # => "ello"
"".lchop      # => ""

def lchop?(prefix : Char | String) : String | Nil #

Returns a newString withprefix removed from the beginning of the string if possible, else returnsnil.

"hello".lchop?('h')   # => "ello"
"hello".lchop?('g')   # => nil
"hello".lchop?("hel") # => "lo"
"hello".lchop?("eh")  # => nil

def lchop? : String | Nil #

Returns a newString with the first char removed from it if possible, else returnsnil.

"hello".lchop? # => "ello"
"".lchop?      # => nil

def lines(chomp : Bool = true) : Array(String) #

Returns an array of the string split into lines.

Both LF (line feed,\n) and CRLF (carriage return line feed,\r\n) are recognized as line delimiters.

Ifchomp is true, the line separator is removed from the end of each line.

"hello\nworld\n".lines                 # => ["hello", "world"]
"hello\nworld\n".lines(chomp: false)   # => ["hello\n", "world\n"]
"hello\nworld\r\n".lines               # => ["hello", "world"]
"hello\nworld\r\n".lines(chomp: false) # => ["hello\n", "world\r\n"]

A trailing line feed is not considered starting a final, empty line. The empty string does not contain any lines.

"hellp\n".lines # => ["hellp"]
"\n".lines      # => [""]
"".lines        # => [] of String
  • #each_line yields each line without allocating an array

def ljust(len : Int, char : Char = ' ') : String #

Adds instances ofchar to right of the string until it is at least size oflen.

"Purple".ljust(8)      # => "Purple  "
"Purple".ljust(8, '-') # => "Purple--"
"Aubergine".ljust(8)   # => "Aubergine"

def ljust(io : IO, len : Int, char : Char = ' ') : Nil #

Adds instances ofchar to right of the string until it is at least size oflen, and then appends the result to the given IO.

io = IO::Memory.new
"Purple".ljust(io, 8, '-')
io.to_s # => "Purple--"

def lstrip(char : Char) : String #

Returns a new string with leading occurrences ofchar removed.

"aaabcdaaa".lstrip('a') # => "bcdaaa"

def lstrip(chars : String) : String #

Returns a new string where leading occurrences of any char inchars are removed. Thechars argument is not a suffix; rather; all combinations of its values are stripped.

"bcadefcba".lstrip("abc") # => "defcba"

def lstrip : String #

Returns a newString with leading whitespace removed.

"    hello    ".lstrip # => "hello    "
"\tgoodbye\r\n".lstrip # => "goodbye\r\n"

def lstrip(&block : Char -> _) : String #

Returns a new string where leading characters for which the block returns atruthy value are removed.

"bcadefcba".lstrip { |c| 'a' <= c <= 'c' } # => "defcba"

def match(regex : Regex, pos = 0, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Regex::MatchData | Nil #

Finds matches ofregex starting atpos and updates$~ to the result.

"foo".match(/foo/) # => Regex::MatchData("foo")
$~                 # => Regex::MatchData("foo")

"foo".match(/bar/) # => nil
$~                 # raises Exception

def match!(regex : Regex, pos = 0, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Regex::MatchData #

Finds matches ofregex starting atpos and updates$~ to the result. RaisesRegex::Error if there are no matches.

"foo".match!(/foo/) # => Regex::MatchData("foo")
$~                  # => Regex::MatchData("foo")

"foo".match!(/bar/) # => raises Exception

def match_full(regex : Regex) : Regex::MatchData | Nil #

Matches the regular expressionregex against the entire string and returns the resultingMatchData. It also updates$~ with the result.

"foo".match_full(/foo/)  # => Regex::MatchData("foo")
$~                       # => Regex::MatchData("foo")
"fooo".match_full(/foo/) # => nil
$~                       # raises Exception

def match_full!(regex : Regex) : Regex::MatchData #

Matches the regular expressionregex against the entire string and returns the resultingMatchData. It also updates$~ with the result. RaisesRegex::Error if there are no matches.

"foo".match_full!(/foo/)  # => Regex::MatchData("foo")
$~                        # => Regex::MatchData("foo")
"fooo".match_full!(/foo/) # Regex::Error
$~                        # raises Exception

def matches?(regex : Regex, pos = 0, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Bool #

Finds match ofregex like#match, but it returnsBool value. It neither returnsMatchData nor assigns it to the$~ variable.

"foo".matches?(/bar/) # => false
"foo".matches?(/foo/) # => true

# `$~` is not set even if last match succeeds.
$~ # raises Exception

def matches_full?(regex : Regex) : Bool #

Returnstrue if the regular expressionregex matches this string entirely.

"foo".matches_full?(/foo/)  # => true
"fooo".matches_full?(/foo/) # => false

# `$~` is not set even if last match succeeds.
$~ # raises Exception

def partition(search : Char | String) : Tuple(String, String, String) #

Searches separator or pattern (Regex) in the string, and returns aTuple with the part before it, the match, and the part after it. If it is not found, returns str followed by two empty strings.

"hello".partition("l") # => {"he", "l", "lo"}
"hello".partition("x") # => {"hello", "", ""}

def partition(search : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Tuple(String, String, String) #

Searches separator or pattern (Regex) in the string, and returns aTuple with the part before it, the match, and the part after it. If it is not found, returns str followed by two empty strings.

"hello".partition("l") # => {"he", "l", "lo"}
"hello".partition("x") # => {"hello", "", ""}

def presence : self | Nil #

Returnsself unless#blank? istrue in which case it returnsnil.

"a".presence         # => "a"
"".presence          # => nil
"   ".presence       # => nil
"    a    ".presence # => "    a    "
nil.presence         # => nil

config = {"empty" => ""}
config["empty"]?.presence || "default"   # => "default"
config["missing"]?.presence || "default" # => "default"

See also:Nil#presence.


def pretty_print(pp : PrettyPrint) : Nil #

Pretty printsself into the given printer.


def rchop(suffix : Char | String) : String #

Returns a newString withsuffix removed from the end of the string.

"strings".rchop('s')  # => "string"
"string".rchop('x')   # => "string"
"string".rchop("ing") # => "str"
"string".rchop("inx") # => "string"

def rchop : String #

Returns a newString with the last character removed. Applying rchop to an empty string returns an empty string.

"string\r\n".rchop # => "string\r"
"string\n\r".rchop # => "string\n"
"string\n".rchop   # => "string"
"strings".rchop    # => "string"
"x".rchop.rchop    # => ""

def rchop?(suffix : Char | String) : String | Nil #

Returns a newString withsuffix removed from the end of the string if possible, else returnsnil.

"strings".rchop?('s')  # => "string"
"string".rchop?('x')   # => nil
"string".rchop?("ing") # => "str"
"string".rchop?("inx") # => nil

def rchop? : String | Nil #

Returns a newString with the last character removed if possible, else returnsnil.

"string\r\n".rchop? # => "string\r"
"string\n\r".rchop? # => "string\n"
"string\n".rchop?   # => "string"
"strings".rchop?    # => "string"
"".rchop?           # => nil

def reverse : String #

Reverses the order of characters in the string.

"Argentina".reverse # => "anitnegrA"
"racecar".reverse   # => "racecar"

Works on Unicode graphemes (and not codepoints) so combining characters are preserved.

"Noe\u0308l".reverse # => "lëoN"

def rindex(search : Char, offset = size - 1) #

Returns the index of thelast appearance ofsearch in the string, Ifoffset is present, it defines the position toend the search (characters beyond this point are ignored).

"Hello, World".rindex('o')    # => 8
"Hello, World".rindex('Z')    # => nil
"Hello, World".rindex('o', 5) # => 4
"Hello, World".rindex('W', 2) # => nil

def rindex(search : String, offset = size - search.size) : Int32 | Nil #

Returns the index of thelast appearance ofsearch in the string, Ifoffset is present, it defines the position toend the search (characters beyond this point are ignored).

"Hello, World".rindex("orld")    # => 8
"Hello, World".rindex("snorlax") # => nil
"Hello, World".rindex("o", 5)    # => 4
"Hello, World".rindex("W", 2)    # => nil

def rindex(search : Regex, offset = size, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Int32 | Nil #

Returns the index of thelast appearance ofsearch in the string, Ifoffset is present, it defines the position toend the search (characters beyond this point are ignored).

"Hello, World".rindex(/world/i) # => 7
"Hello, World".rindex(/world/)  # => nil
"Hello, World".rindex(/o/, 5)   # => 4
"Hello, World".rindex(/W/, 2)   # => nil

def rindex!(search : Char, offset = size - 1) : Int32 #

Returns the index of thelast appearance ofsearch in the string, Ifoffset is present, it defines the position toend the search (characters beyond this point are ignored). RaisesEnumerable::NotFoundError ifsearch does not occur inself.

"Hello, World".rindex!('o')    # => 8
"Hello, World".rindex!('Z')    # raises Enumerable::NotFoundError
"Hello, World".rindex!('o', 5) # => 4
"Hello, World".rindex!('W', 2) # raises Enumerable::NotFoundError

def rindex!(search : String, offset = size - search.size) : Int32 #

Returns the index of thelast appearance ofsearch in the string, Ifoffset is present, it defines the position toend the search (characters beyond this point are ignored). RaisesEnumerable::NotFoundError ifsearch does not occur inself.

"Hello, World".rindex!("orld")    # => 8
"Hello, World".rindex!("snorlax") # raises Enumerable::NotFoundError
"Hello, World".rindex!("o", 5)    # => 4
"Hello, World".rindex!("W", 2)    # raises Enumerable::NotFoundError

def rindex!(search : Regex, offset = size, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Int32 #

Returns the index of thelast appearance ofsearch in the string, Ifoffset is present, it defines the position toend the search (characters beyond this point are ignored). RaisesEnumerable::NotFoundError ifsearch does not occur inself.

"Hello, World".rindex!(/world/i) # => 7
"Hello, World".rindex!(/world/)  # raises Enumerable::NotFoundError
"Hello, World".rindex!(/o/, 5)   # => 4
"Hello, World".rindex!(/W/, 2)   # raises Enumerable::NotFoundError

def rjust(len : Int, char : Char = ' ') : String #

Adds instances ofchar to left of the string until it is at least size oflen.

"Purple".rjust(8)      # => "  Purple"
"Purple".rjust(8, '-') # => "--Purple"
"Aubergine".rjust(8)   # => "Aubergine"

def rjust(io : IO, len : Int, char : Char = ' ') : Nil #

Adds instances ofchar to left of the string until it is at least size oflen, and then appends the result to the given IO.

io = IO::Memory.new
"Purple".rjust(io, 8, '-')
io.to_s # => "--Purple"

def rpartition(search : Char | String) : Tuple(String, String, String) #

Searches separator or pattern (Regex) in the string from the end of the string, and returns aTuple with the part before it, the match, and the part after it. If it is not found, returns two empty strings and str.

"hello".rpartition("l")  # => {"hel", "l", "o"}
"hello".rpartition("x")  # => {"", "", "hello"}
"hello".rpartition(/.l/) # => {"he", "ll", "o"}

def rpartition(search : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Tuple(String, String, String) #

Searches separator or pattern (Regex) in the string from the end of the string, and returns aTuple with the part before it, the match, and the part after it. If it is not found, returns two empty strings and str.

"hello".rpartition("l")  # => {"hel", "l", "o"}
"hello".rpartition("x")  # => {"", "", "hello"}
"hello".rpartition(/.l/) # => {"he", "ll", "o"}

def rstrip(char : Char) : String #

Returns a new string with trailing occurrences ofchar removed.

"aaabcdaaa".rstrip('a') # => "aaabcd"

def rstrip(chars : String) : String #

Returns a new string where trailing occurrences of any char inchars are removed. Thechars argument is not a suffix; rather; all combinations of its values are stripped.

"abcdefcba".rstrip("abc") # => "abcdef"

def rstrip : String #

Returns a newString with trailing whitespace removed.

"    hello    ".rstrip # => "    hello"
"\tgoodbye\r\n".rstrip # => "\tgoodbye"

def rstrip(&block : Char -> _) : String #

Returns a new string where trailing characters for which the block returns atruthy value are removed.

"bcadefcba".rstrip { |c| 'a' <= c <= 'c' } # => "bcadef"

def scan(pattern : String, &) : self #

Searches the string for instances ofpattern, yielding the matched string for each match.


def scan(pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None, &) : self #

Searches the string for instances ofpattern, yielding aRegex::MatchData for each match.


def scan(pattern : String) : Array(String) #

Searches the string for instances ofpattern, returning an array of the matched string for each match.


def scan(pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Array(Regex::MatchData) #

Searches the string for instances ofpattern, returning anArray ofRegex::MatchData for each match.


def scrub(replacement = Char::REPLACEMENT) : String #

Returns a String where bytes that are invalid in the UTF-8 encoding are replaced withreplacement.


def size : Int32 #

Returns the number of unicode codepoints in this string.

"hello".size # => 5
"你好".size    # => 2

def split(limit : Int32 | Nil = nil) : Array(String) #

Makes an array by splitting the string on any amount of ASCII whitespace characters (and removing that whitespace).

Iflimit is present, up tolimit new strings will be created, with the entire remainder added to the last string.

old_pond = "
  Old pond
  a frog leaps in
  water's sound
"
old_pond.split    # => ["Old", "pond", "a", "frog", "leaps", "in", "water's", "sound"]
old_pond.split(3) # => ["Old", "pond", "a frog leaps in\n  water's sound\n"]

def split(limit : Int32 | Nil = nil, &block : String -> _) #

Splits the string after any amount of ASCII whitespace characters and yields each non-whitespace part to a block.

Iflimit is present, up tolimit new strings will be created, with the entire remainder added to the last string.

ary = [] of String
old_pond = "
  Old pond
  a frog leaps in
  water's sound
"

old_pond.split { |s| ary << s }
ary # => ["Old", "pond", "a", "frog", "leaps", "in", "water's", "sound"]
ary.clear

old_pond.split(3) { |s| ary << s }
ary # => ["Old", "pond", "a frog leaps in\n  water's sound\n"]

def split(separator : Char, limit = nil, *, remove_empty = false) : Array(String) #

Makes anArray by splitting the string on the given characterseparator (and removing that character).

Iflimit is present, up tolimit new strings will be created, with the entire remainder added to the last string.

Ifremove_empty istrue, any empty strings are removed from the result.

"foo,,bar,baz".split(',')                     # => ["foo", "", "bar", "baz"]
"foo,,bar,baz".split(',', remove_empty: true) # => ["foo", "bar", "baz"]
"foo,bar,baz".split(',', 2)                   # => ["foo", "bar,baz"]

def split(separator : Char, limit = nil, *, remove_empty = false, &block : String -> _) #

Splits the string after each characterseparator and yields each part to a block.

Iflimit is present, up tolimit new strings will be created, with the entire remainder added to the last string.

Ifremove_empty istrue, any empty strings are not yielded.

ary = [] of String

"foo,,bar,baz".split(',') { |string| ary << string }
ary # => ["foo", "", "bar", "baz"]
ary.clear

"foo,,bar,baz".split(',', remove_empty: true) { |string| ary << string }
ary # => ["foo", "bar", "baz"]
ary.clear

"foo,bar,baz".split(',', 2) { |string| ary << string }
ary # => ["foo", "bar,baz"]

def split(separator : String, limit = nil, *, remove_empty = false) : Array(String) #

Makes anArray by splitting the string onseparator (and removing instances ofseparator).

Iflimit is present, the array will be limited tolimit items and the final item will contain the remainder of the string.

Ifseparator is an empty string (""), the string will be separated into one-character strings.

Ifremove_empty istrue, any empty strings are removed from the result.

long_river_name = "Mississippi"
long_river_name.split("ss")                    # => ["Mi", "i", "ippi"]
long_river_name.split("i")                     # => ["M", "ss", "ss", "pp", ""]
long_river_name.split("i", remove_empty: true) # => ["M", "ss", "ss", "pp"]
long_river_name.split("")                      # => ["M", "i", "s", "s", "i", "s", "s", "i", "p", "p", "i"]

def split(separator : String, limit = nil, *, remove_empty = false, &block : String -> _) #

Splits the string after each stringseparator and yields each part to a block.

Iflimit is present, the array will be limited tolimit items and the final item will contain the remainder of the string.

Ifseparator is an empty string (""), the string will be separated into one-character strings.

Ifremove_empty istrue, any empty strings are removed from the result.

ary = [] of String
long_river_name = "Mississippi"

long_river_name.split("ss") { |s| ary << s }
ary # => ["Mi", "i", "ippi"]
ary.clear

long_river_name.split("i") { |s| ary << s }
ary # => ["M", "ss", "ss", "pp", ""]
ary.clear

long_river_name.split("i", remove_empty: true) { |s| ary << s }
ary # => ["M", "ss", "ss", "pp"]
ary.clear

long_river_name.split("") { |s| ary << s }
ary # => ["M", "i", "s", "s", "i", "s", "s", "i", "p", "p", "i"]

def split(separator : Regex, limit = nil, *, remove_empty = false, options : Regex::MatchOptions = Regex::MatchOptions::None) : Array(String) #

Makes anArray by splitting the string onseparator (and removing instances ofseparator).

Ifseparator is an empty regex (//), the string will be separated into one-character strings. Ifseparator defines any capture groups, their matches are also included in the result.

Iflimit is present,separator will be matched at mostlimit - 1 times, and the final item will contain the remainder of the string. The array may contain more thanlimit items if capture groups are present.

Ifremove_empty istrue, any empty strings are removed from the result. This does not affect matches fromseparator's capture groups.

long_river_name = "Mississippi"
long_river_name.split(/s+/)  # => ["Mi", "i", "ippi"]
long_river_name.split(//)    # => ["M", "i", "s", "s", "i", "s", "s", "i", "p", "p", "i"]
long_river_name.split(/(i)/) # => ["M", "i", "ss", "i", "ss", "i", "pp", "i", ""]

def split(separator : Regex, limit = nil, *, remove_empty = false, options : Regex::MatchOptions = Regex::MatchOptions::None, &block : String -> _) #

Splits the string after each regexseparator and yields each part to a block.

Ifseparator is an empty regex (//), the string will be separated into one-character strings. Ifseparator defines any capture groups, their matches are also yielded in order.

Iflimit is present,separator will be matched at mostlimit - 1 times, and the final item will contain the remainder of the string. More thanlimit items may be yielded in total if capture groups are present.

Ifremove_empty istrue, any empty strings are not yielded. This does not affect matches fromseparator's capture groups.

ary = [] of String
long_river_name = "Mississippi"

long_river_name.split(/s+/) { |s| ary << s }
ary # => ["Mi", "i", "ippi"]
ary.clear

long_river_name.split(//) { |s| ary << s }
ary # => ["M", "i", "s", "s", "i", "s", "s", "i", "p", "p", "i"]
ary.clear

long_river_name.split(/(i)/) { |s| ary << s }
ary # => ["M", "i", "ss", "i", "ss", "i", "pp", "i", ""]

def squeeze(&) : String #

Yields each char in this string to the block. Returns a newString, that has all characters removed, that were the same as the previous one and for which the given block returned a truthy value.

"aaabbbccc".squeeze &.in?('a', 'b') # => "abccc"
"aaabbbccc".squeeze &.in?('a', 'c') # => "abbbc"

def squeeze(char : Char) : String #

Returns a newString, with all runs of char replaced by one instance.

"a    bbb".squeeze(' ') # => "a bbb"

def squeeze : String #

Returns a newString, that has all characters removed, that were the same as the previous one.

"a       bbb".squeeze # => "a b"

def squeeze(*sets : String) : String #

Sets should be a list of strings following the rules described atChar#in_set?. Returns a newString with all runs of the same character replaced by one instance, if they match the given set.

If no set is given, all characters are matched.

"aaabbbcccddd".squeeze("b-d") # => "aaabcd"
"a       bbb".squeeze         # => "a b"

def starts_with?(str : String) : Bool #

Returnstrue if this string starts with the givenstr.

"hello".starts_with?("h")  # => true
"hello".starts_with?("he") # => true
"hello".starts_with?("hu") # => false

def starts_with?(char : Char) : Bool #

Returnstrue if this string starts with the givenchar.

"hello".starts_with?('h') # => true
"hello".starts_with?('e') # => false

def starts_with?(re : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : Bool #

Returnstrue if the regular expressionre matches at the start of this string.

"22hello".starts_with?(/[0-9]/) # => true
"22hello".starts_with?(/[a-z]/) # => false
"h22".starts_with?(/[a-z]/)     # => true
"h22".starts_with?(/[A-Z]/)     # => false
"h22".starts_with?(/[a-z]{2}/)  # => false
"hh22".starts_with?(/[a-z]{2}/) # => true

def strip(char : Char) : String #

Returns a new string where leading and trailing occurrences ofchar are removed.

"aaabcdaaa".strip('a') # => "bcd"

def strip(chars : String) : String #

Returns a new string where leading and trailing occurrences of any char inchars are removed. Thechars argument is not a prefix or suffix; rather; all combinations of its values are stripped.

"abcdefcba".strip("abc") # => "def"

def strip : String #

Returns a newString with leading and trailing whitespace removed.

"    hello    ".strip # => "hello"
"\tgoodbye\r\n".strip # => "goodbye"

def strip(&block : Char -> _) : String #

Returns a new string where leading and trailing characters for which the block returns atruthy value are removed.

"bcadefcba".strip { |c| 'a' <= c <= 'c' } # => "def"

def sub(string : String, &) : String #

Returns aString where the first occurrences of the givenstring is replaced with the block's value.

"hello yellow".sub("ll") { "dd" } # => "heddo yellow"

def sub(pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None, &) : String #

Returns aString where the first occurrence ofpattern is replaced by the block's return value.

"hello".sub(/./) { |s| s[0].ord.to_s + ' ' } # => "104 ello"

def sub(&block : Char -> _) : String #

Returns a newString where the first character is yielded to the given block and replaced by its return value.

"hello".sub { |char| char + 1 } # => "iello"
"hello".sub { "hi" }            # => "hiello"

def sub(char : Char, replacement) : String #

Returns aString where the first occurrence ofchar is replaced by replacement.

"hello".sub('l', "lo")      # => "helolo"
"hello world".sub('o', 'a') # => "hella world"

def sub(pattern : Regex, hash : Hash(String, _) | NamedTuple, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

Returns aString where the first occurrences of the givenpattern is replaced with the matching entry from thehash of replacements. If the first match is not included in thehash, nothing is replaced.

"hello".sub(/(he|l|o)/, {"he": "ha", "l": "la"}) # => "hallo"
"hello".sub(/(he|l|o)/, {"l": "la"})             # => "hello"

def sub(string : String, replacement) : String #

Returns aString where the first occurrences of the givenstring is replaced with the givenreplacement.

"hello yellow".sub("ll", "dd") # => "heddo yellow"

def sub(index : Int, replacement : Char) : String #

Returns a newString with the character at the given index replaced byreplacement.

"hello".sub(1, 'a') # => "hallo"

def sub(index : Int, replacement : String) : String #

Returns a newString with the character at the given index replaced byreplacement.

"hello".sub(1, "eee") # => "heeello"

def sub(range : Range, replacement : Char) : String #

Returns a newString with characters at the given range replaced byreplacement.

"hello".sub(1..2, 'a') # => "halo"

def sub(range : Range, replacement : String) : String #

Returns a newString with characters at the given range replaced byreplacement.

"hello".sub(1..2, "eee") # => "heeelo"

def sub(pattern : Regex, replacement, backreferences = true, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

Returns aString where the first occurrence ofpattern is replaced by replacement

"hello".sub(/[aeiou]/, "*") # => "h*llo"

Withinreplacement, the special match variable$~ will not refer to the current match.

Ifbackreferences istrue (the default value),replacement can include backreferences:

"hello".sub(/[aeiou]/, "(\\0)") # => "h(e)llo"

When substitution is performed, any backreferences found inreplacement will be replaced with the contents of the corresponding capture group in pattern. Backreferences to capture groups that were not present in pattern or that did not match will be skipped. SeeRegex for information about capture groups.

Backreferences are expressed in the form"\\d", whered is a group number, or"\\k&lt;name>" wherename is the name of a named capture group. A sequence of literal characters resembling a backreference can be expressed by placing"\\" before the sequence.

"foo".sub(/o/, "x\\0x")                  # => "fxoxo"
"foofoo".sub(/(?<bar>oo)/, "|\\k<bar>|") # => "f|oo|foo"
"foo".sub(/o/, "\\\\0")                  # => "f\\0o"

RaisesArgumentError if an incomplete named back-reference is present in replacement.

RaisesIndexError if a named group referenced inreplacement is not present inpattern.


def sub(hash : Hash(Char, _)) : String #

Returns aString where the first char in the string matching a key in the givenhash is replaced by the corresponding hash value.

"hello".sub({'a' => 'b', 'l' => 'd'}) # => "hedlo"

def succ : String #

Returns the successor of the string. The successor is calculated by incrementing characters starting from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the string. Incrementing a digit always results in another digit, and incrementing a letter results in another letter of the same case.

If the increment generates a&quot;carry&quot;, the character to the left of it is incremented. This process repeats until there is no carry, adding an additional character if necessary.

"abcd".succ      # => "abce"
"THX1138".succ   # => "THX1139"
"((koala))".succ # => "((koalb))"
"1999zzz".succ   # => "2000aaa"
"ZZZ9999".succ   # => "AAAA0000"
"***".succ       # => "**+"

def titleize(io : IO, options : Unicode::CaseOptions = :none, *, underscore_to_space : Bool = false) : Nil #

Writes a titleized version ofself to the givenio. Optionally, ifunderscore_to_space istrue, underscores (_) will be converted to a space and the following letter converted to uppercase.

io = IO::Memory.new
"x-men: the last stand".titleize io
io.to_s # => "X-men: The Last Stand"

def titleize(options : Unicode::CaseOptions = :none, *, underscore_to_space : Bool = false) : String #

Returns a newString with the first letter after any space converted to uppercase and every other letter converted to lowercase. Optionally, ifunderscore_to_space istrue, underscores (_) will be converted to a space and the following letter converted to uppercase.

"hEllO tAb\tworld".titleize                   # => "Hello Tab\tWorld"
"  spaces before".titleize                    # => "  Spaces Before"
"x-men: the last stand".titleize              # => "X-men: The Last Stand"
"foo_bar".titleize                            # => "Foo_bar"
"foo_bar".titleize(underscore_to_space: true) # => "Foo Bar"

def to_big_d : BigDecimal #

Convertsself toBigDecimal.

require "big"
"1212341515125412412412421".to_big_d

def to_big_f : BigFloat #

Convertsself to aBigFloat.

require "big"
"1234.0".to_big_f

def to_big_i(base : Int32 = 10) : BigInt #

Returns aBigInt from this string, in the givenbase.

RaisesArgumentError if this string doesn't denote a valid integer.

require "big"

"3a060dbf8d1a5ac3e67bc8f18843fc48".to_big_i(16)

def to_f(whitespace : Bool = true, strict : Bool = true) : Float64 #

Returns the result of interpreting characters in this string as a floating point number (Float64). This method raises an exception if the string is not a valid float representation or exceeds the range of the data type. Values representing infinity or NaN are considered valid.

Options:

  • whitespace: iftrue, leading and trailing whitespaces are allowed
  • strict: iftrue, extraneous characters past the end of the number are disallowed, unlesswhitespace is alsotrue and all the trailing characters past the number are whitespaces
"123.45e1".to_f                # => 1234.5
"45.67 degrees".to_f           # raises ArgumentError
"thx1138".to_f(strict: false)  # raises ArgumentError
" 1.2".to_f(whitespace: false) # raises ArgumentError
"1.2foo".to_f(strict: false)   # => 1.2

def to_f32(whitespace : Bool = true, strict : Bool = true) : Float32 #

Same as#to_f but returns a Float32.


def to_f32?(whitespace : Bool = true, strict : Bool = true) : Float32 | Nil #

Same as#to_f? but returns a Float32.


def to_f64(whitespace : Bool = true, strict : Bool = true) : Float64 #

Returns the result of interpreting characters in this string as a floating point number (Float64). This method raises an exception if the string is not a valid float representation or exceeds the range of the data type. Values representing infinity or NaN are considered valid.

Options:

  • whitespace: iftrue, leading and trailing whitespaces are allowed
  • strict: iftrue, extraneous characters past the end of the number are disallowed, unlesswhitespace is alsotrue and all the trailing characters past the number are whitespaces
"123.45e1".to_f                # => 1234.5
"45.67 degrees".to_f           # raises ArgumentError
"thx1138".to_f(strict: false)  # raises ArgumentError
" 1.2".to_f(whitespace: false) # raises ArgumentError
"1.2foo".to_f(strict: false)   # => 1.2

def to_f64?(whitespace : Bool = true, strict : Bool = true) : Float64 | Nil #

Returns the result of interpreting characters in this string as a floating point number (Float64). This method returnsnil if the string is not a valid float representation or exceeds the range of the data type. Values representing infinity or NaN are considered valid.

Options:

  • whitespace: iftrue, leading and trailing whitespaces are allowed
  • strict: iftrue, extraneous characters past the end of the number are disallowed, unlesswhitespace is alsotrue and all the trailing characters past the number are whitespaces
"123.45e1".to_f?                # => 1234.5
"45.67 degrees".to_f?           # => nil
"thx1138".to_f?                 # => nil
" 1.2".to_f?(whitespace: false) # => nil
"1.2foo".to_f?(strict: false)   # => 1.2

def to_f?(whitespace : Bool = true, strict : Bool = true) : Float64 | Nil #

Returns the result of interpreting characters in this string as a floating point number (Float64). This method returnsnil if the string is not a valid float representation or exceeds the range of the data type. Values representing infinity or NaN are considered valid.

Options:

  • whitespace: iftrue, leading and trailing whitespaces are allowed
  • strict: iftrue, extraneous characters past the end of the number are disallowed, unlesswhitespace is alsotrue and all the trailing characters past the number are whitespaces
"123.45e1".to_f?                # => 1234.5
"45.67 degrees".to_f?           # => nil
"thx1138".to_f?                 # => nil
" 1.2".to_f?(whitespace: false) # => nil
"1.2foo".to_f?(strict: false)   # => 1.2

def to_i(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) #

Returns the result of interpreting leading characters in this string as an integer basebase (between 2 and 36).

If there is not a valid number at the start of this string, or if the resulting integer doesn't fit anInt32, anArgumentError is raised.

Options:

  • whitespace: iftrue, leading and trailing whitespaces are allowed
  • underscore: iftrue, underscores in numbers are allowed
  • prefix: iftrue, the prefixes"0x","0o" and"0b" override the base
  • strict: iftrue, extraneous characters past the end of the number are disallowed, unlesswhitespace is alsotrue and all the trailing characters past the number are whitespaces
  • leading_zero_is_octal: iftrue, then a number prefixed with"0" will be treated as an octal
"12345".to_i             # => 12345
"0a".to_i                # raises ArgumentError
"hello".to_i             # raises ArgumentError
"0a".to_i(16)            # => 10
"1100101".to_i(2)        # => 101
"1100101".to_i(8)        # => 294977
"1100101".to_i(10)       # => 1100101
"1100101".to_i(base: 16) # => 17826049

"12_345".to_i                   # raises ArgumentError
"12_345".to_i(underscore: true) # => 12345

"  12345  ".to_i                    # => 12345
"  12345  ".to_i(whitespace: false) # raises ArgumentError

"0x123abc".to_i               # raises ArgumentError
"0x123abc".to_i(prefix: true) # => 1194684

"99 red balloons".to_i                # raises ArgumentError
"99 red balloons".to_i(strict: false) # => 99

"0755".to_i                              # => 755
"0755".to_i(leading_zero_is_octal: true) # => 493

def to_i(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i, but returns the block's value if there is not a valid number at the start of this string, or if the resulting integer doesn't fit anInt32.

"12345".to_i { 0 } # => 12345
"hello".to_i { 0 } # => 0

def to_i128(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int128 #

Same as#to_i but returns anInt128.


def to_i128(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anInt128 or the block's value.


def to_i128?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int128 | Nil #

Same as#to_i but returns anInt128 ornil.


def to_i16(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int16 #

Same as#to_i but returns anInt16.


def to_i16(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anInt16 or the block's value.


def to_i16?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int16 | Nil #

Same as#to_i but returns anInt16 ornil.


def to_i32(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int32 #

Same as#to_i.


def to_i32(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i.


def to_i32?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int32 | Nil #

Same as#to_i.


def to_i64(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int64 #

Same as#to_i but returns anInt64.


def to_i64(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anInt64 or the block's value.


def to_i64?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int64 | Nil #

Same as#to_i but returns anInt64 ornil.


def to_i8(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int8 #

Same as#to_i but returns anInt8.


def to_i8(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anInt8 or the block's value.


def to_i8?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : Int8 | Nil #

Same as#to_i but returns anInt8 ornil.


def to_i?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) #

Same as#to_i, but returnsnil if there is not a valid number at the start of this string, or if the resulting integer doesn't fit anInt32.

"12345".to_i?             # => 12345
"99 red balloons".to_i?   # => nil
"0a".to_i?(strict: false) # => 0
"hello".to_i?             # => nil

def to_json(json : JSON::Builder) : Nil #

def to_json_object_key : String #

def to_s(io : IO) : Nil #

Appendsself toio.


def to_s : String #

Returnsself.


def to_slice : Bytes #

Returns the underlying bytes of this String.

The returned slice is read-only.

May contain invalid UTF-8 byte sequences;#scrub may be used to first obtain aString that is guaranteed to be valid UTF-8.


def to_u128(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt128 #

Same as#to_i but returns anUInt128.


def to_u128(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anUInt128 or the block's value.


def to_u128?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt128 | Nil #

Same as#to_i but returns anUInt128 ornil.


def to_u16(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt16 #

Same as#to_i but returns anUInt16.


def to_u16(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anUInt16 or the block's value.


def to_u16?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt16 | Nil #

Same as#to_i but returns anUInt16 ornil.


def to_u32(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt32 #

Same as#to_i but returns anUInt32.


def to_u32(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anUInt32 or the block's value.


def to_u32?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt32 | Nil #

Same as#to_i but returns anUInt32 ornil.


def to_u64(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt64 #

Same as#to_i but returns anUInt64.


def to_u64(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anUInt64 or the block's value.


def to_u64?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt64 | Nil #

Same as#to_i but returns anUInt64 ornil.


def to_u8(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt8 #

Same as#to_i but returns anUInt8.


def to_u8(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false, &) #

Same as#to_i but returns anUInt8 or the block's value.


def to_u8?(base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : UInt8 | Nil #

Same as#to_i but returns anUInt8 ornil.


def to_unsafe : Pointer(UInt8) #

Returns a pointer to the underlying bytes of this String.

May contain invalid UTF-8 byte sequences;#scrub may be used to first obtain aString that is guaranteed to be valid UTF-8.


def to_utf16 : Slice(UInt16) #

Returns the UTF-16 encoding of the givenstring.

Invalid chars (in the range U+D800..U+DFFF) are encoded with the unicode replacement char value0xfffd.

The byte following the end of this slice (but not included in it) is defined to be zero. This allows passing the result of this function into C functions that expect a null-terminatedUInt16*.

"hi 𐂥".to_utf16 # => Slice[104_u16, 105_u16, 32_u16, 55296_u16, 56485_u16]

def to_yaml(yaml : YAML::Nodes::Builder) : Nil #

def tr(from : String, to : String) : String #

Returns a new string_tr_anslating characters usingfrom andto as a map. Ifto is shorter thanfrom, the last character into is used for the rest. Ifto is empty, this acts likeString#delete.

"aabbcc".tr("abc", "xyz") # => "xxyyzz"
"aabbcc".tr("abc", "x")   # => "xxxxxx"
"aabbcc".tr("a", "xyz")   # => "xxbbcc"

def underscore(options : Unicode::CaseOptions = :none) : String #

Converts camelcase boundaries to underscores.

"DoesWhatItSaysOnTheTin".underscore                         # => "does_what_it_says_on_the_tin"
"PartyInTheUSA".underscore                                  # => "party_in_the_usa"
"HTTP_CLIENT".underscore                                    # => "http_client"
"3.14IsPi".underscore                                       # => "3.14_is_pi"
"InterestingImage".underscore(Unicode::CaseOptions::Turkic) # => "ınteresting_ımage"

def underscore(io : IO, options : Unicode::CaseOptions = :none) : Nil #

Writes an underscored version ofself to the givenio.

io = IO::Memory.new
"DoesWhatItSaysOnTheTin".underscore io
io.to_s # => "does_what_it_says_on_the_tin"

def unicode_normalize(form : Unicode::NormalizationForm = :nfc) : String #

Returns the result of normalizing thisString according to the given Unicode normalization form.

str = "\u{1E9B}\u{0323}"                # => "ẛ̣"
str.unicode_normalize.codepoints        # => [0x1E9B, 0x0323]
str.unicode_normalize(:nfd).codepoints  # => [0x017F, 0x0323, 0x0307]
str.unicode_normalize(:nfkc).codepoints # => [0x1E69]
str.unicode_normalize(:nfkd).codepoints # => [0x0073, 0x0323, 0x0307]

def unicode_normalize(io : IO, form : Unicode::NormalizationForm = :nfc) : Nil #

Normalizes thisString according to the given Unicode normalization form and writes the result to the givenio.


def unicode_normalized?(form : Unicode::NormalizationForm = :nfc) : Bool #

Returns whether thisString is in the given Unicode normalization form.

foo = "\u{00E0}"              # => "à"
foo.unicode_normalized?       # => true
foo.unicode_normalized?(:nfd) # => false

bar = "\u{0061}\u{0300}"      # => "à"
bar.unicode_normalized?       # => false
bar.unicode_normalized?(:nfd) # => true

def unsafe_byte_at(index : Int) : UInt8 #

Returns the byte at the givenindex without bounds checking.

DEPRECATED Useto_unsafe[index] instead.


def unsafe_byte_slice(byte_offset, count) : Slice #

Returnscount of underlying bytes of this String starting at givenbyte_offset.

The returned slice is read-only.


def unsafe_byte_slice(byte_offset) : Slice #

Returns the underlying bytes of this String starting at givenbyte_offset.

The returned slice is read-only.


def upcase(options : Unicode::CaseOptions = :none) : String #

Returns a newString with each lowercase letter replaced with its uppercase counterpart.

"hEllO".upcase # => "HELLO"

def upcase(io : IO, options : Unicode::CaseOptions = :none) : Nil #

Writes a upcased version ofself to the givenio.

io = IO::Memory.new
"hEllO".upcase io
io.to_s # => "HELLO"

def valid_encoding? : Bool #

Returnstrue if this String is encoded correctly according to the UTF-8 encoding.