Strings
Build, search, slice and format text.
On this page
A String is read-only text, normally UTF-8. Methods that change text, such as upper() or replace(), return a new string.
Write a string#
fn main() {
let name = "Ada"
println("Hello " + name + "!") // concatenation
println("Hello %name!") // insert a variable
println("Twice: %{name.length * 2}") // insert an expression
println("Cost: \%5") // a literal %
println(r"Raw: %name\n") // raw string, no escapes
println("Tab:\tquote:\" slash:\\")
}
A string literal may span several lines. Any value that converts to a String can go inside %{ }, numbers included.
Inspect text#
fn main() {
let text = "Hello, World"
println(text.length) // 12 (bytes)
println(text.starts_with("Hello")) // true
println(text.contains("World")) // true
println(text.index_of("World") !? 0) // 7
println(text.count("l")) // 3
println(text.is_empty()) // false
println(text == "Hello, World") // true
}
| Method | Returns |
|---|---|
length |
Number of bytes |
starts_with(s), ends_with(s), contains(s) |
bool |
index_of(s), last_index_of(s) |
Byte offset; throws when not found |
count(s) |
How often s occurs |
is_empty() |
bool |
is_integer(), is_number(), is_alpha(), is_alpha_numeric() |
bool |
equals_ignore_ascii_case(s) |
bool |
Strings compare with == and sort with < and > in byte order.
Change text#
fn main() {
let text = " Hello, World ".trim()
println(text.upper()) // HELLO, WORLD
println(text.replace("World", "Valk")) // Hello, Valk
println("--a--".trim("-")) // a
println("ab".repeat(3)) // ababab
println("7".pad_left('0', 3)) // 007
}
| Method | Result |
|---|---|
trim(), ltrim(), rtrim() |
Without whitespace, or without a given part |
lower(), upper() |
Unicode case mapping |
replace(part, with) |
Every occurrence replaced |
repeat(n) |
n copies |
pad_left(char, length), pad_right(char, length) |
Padded to length bytes |
escape(), unescape() |
Backslash escapes added or removed |
Split and join#
fn main() {
let parts = "red,green,blue".split(",")
println(parts.length) // 3
println("a=b=c".split("=", 2).join(" | ")) // a | b=c
each "one two three".words() as word {
print("[%word]") // [one][two][three]
}
println("")
each "first\nsecond".lines() as line : println(line)
}
split(on, limit) keeps empty parts; a limit returns at most that many parts. words() splits at whitespace and skips empty parts. join on an array puts a divider between items.
Take part of a string#
fn main() {
let text = "Hello, World"
println(text.range(0, 5)) // Hello
println(text[7 .. 5]) // World
println(text[0]) // 72
println(text[0] == 'H') // true
each "abc" as byte : print(byte.to(String) + " ") // 97 98 99
println("")
}
A range is a start and a length, in bytes: text[7 .. 5] is five bytes starting at offset 7. text[i] is one byte (u8), and each over a string visits its bytes.
Unicode characters#
Byte offsets cut through multi-byte characters. The utf8 group counts characters instead:
fn main() {
let text = "héllo"
println(text.length) // 6 bytes
println(text.utf8.length) // 5 characters
println(text.utf8.range(1, 2)) // él
println(text.utf8.get(1)) // é
each text.utf8.chars() as ch : print(ch + " ") // h é l l o
println("")
}
Each character is returned as a String. A visible character, such as an emoji with a skin tone, can consist of several code points.
Build long text#
Repeated + copies the text each time. For text built in a loop, write into a ByteBuffer:
fn main() {
let out = ByteBuffer.new()
each 1 .. 3 as i {
out.write("line %i\n")
}
out.write_byte('!')
print(out.to_string()) // line 1, line 2, line 3, !
println("")
}
To build a string from a list, collect the parts in an Array[String] and call join.
Format numbers#
| Code | Result |
|---|---|
"%n" |
Shortest form: 3.5, 3, 42 |
x.to_string(2) |
Two decimals: 3.14 |
n.to(String).pad_left('0', 4) |
Zero-padded: 0042 |
See Variables & types for turning text into numbers, Regular expressions for pattern matching, and Terminal output for colors.
