Working with text
Strings are for names, messages and anything a text in the level should say. This page shows how to take them apart, put them together and search them.
The everyday tools
Every string has the functions of the string library as its own, called with a colon:
local name = "Pathfinder"
print(#name)
print(name:upper(), name:lower())
print(name:sub(1, 4)) -- from place 1 to place 4
print(name:sub(-6)) -- a place below 0 counts from the end
print(name:rep(2, " "))
print(name:reverse())It prints
10
PATHFINDER pathfinder
Path
finder
Pathfinder Pathfinder
rednifhtaPname:upper() is the same as string.upper(name). A string never changes: each of these gives a new string, and name stays as it was.
A string written out needs brackets round it before the colon: ("abc"):upper().
Putting text together
.. joins. In a backtick string, {...} puts a value in. string.format gives the most control over how a number looks:
local seconds = 83.456
print("Time: " .. seconds)
print(`Time: {math.round(seconds, 1)} s`)
print(string.format("Time: %.1f s", seconds))
print(string.format("%d:%02d", seconds // 60, math.floor(seconds % 60)))It prints
Time: 83.456
Time: 83.5 s
Time: 83.5 s
1:23The codes string.format knows:
| Code | Shows | Example |
|---|---|---|
%d | A whole number (round it first: %d refuses 2.5) | %d of 42 is 42 |
%.2f | A number with that many decimals | %.2f of 3.14159 is 3.14 |
%s | Any value, as text | %s of true is true |
%5d %5s | Padded with spaces to 5 wide, at the right | %5s of "ab" is three spaces and ab |
%-5s | The same, padded at the left | |
%05d | Padded with zeros | %05d of 42 is 00042 |
%x | A whole number in base 16 | %x of 255 is ff |
%% | A percent sign |
table.concat joins a whole list, with something between the pieces:
print(table.concat({ "red", "green", "blue" }, " and "))It prints
red and green and blueCutting text up
local line = " saw, block ,spike "
local parts = string.split(line, ",")
for i, part in parts do
parts[i] = string.trim(part) -- without the spaces at its ends
end
print(table.concat(parts, "|"))
print(table.concat(string.split("abc", ""), "-")) -- "" cuts it into lettersIt prints
saw|block|spike
a-b-cFinding text
find says where something is in a string: where it starts and where it ends, or nil when it is not there.
local text = "the red door"
print(text:find("red"))
print(text:find("blue"))
if text:find("door") then
print("it mentions a door")
endIt prints
5 7
nil
it mentions a doorPatterns
find, match, gmatch and gsub do not only look for exact text. They look for a pattern: a description of what the text should look like. In a pattern, % followed by a letter stands for a kind of character:
| Written | Stands for |
|---|---|
%d | A digit |
%a | A letter (a to z, A to Z) |
%w | A letter or a digit |
%s | A space, a tab or a line break |
%l %u | A small letter, a capital letter |
%p | A punctuation sign |
. | Any character at all |
[abc] | One of these; [a-f] one from a to f; [^abc] any but these |
The capital of a letter means the opposite: %D is anything but a digit.
After any of them, a sign says how many:
| Sign | Means |
|---|---|
+ | One or more, as many as possible |
* | None or more, as many as possible |
- | None or more, as few as possible |
? | One or none |
^ at the start of a pattern means "at the start of the text", $ at its end means "at the end of the text".
Brackets catch what matched inside them, and that is what match gives back:
print(("level 12"):match("%d+"))
print(("width=30"):match("(%a+)=(%d+)"))
print((" padded "):match("^%s*(.-)%s*$") .. "|")
print(("hello"):match("%d+"))It prints
12
width 30
padded|
nilgmatch goes through every match, in a for loop:
for word in ("stay on the floor"):gmatch("%a+") do
print(word)
endIt prints
stay
on
the
floorgsub replaces every match and gives the new string (and, after it, how many it replaced). The replacement can be text, where %1 stands for what the first pair of brackets caught, or a function that is given the match and returns what to put there:
print((("3 coins, 12 gems"):gsub("%d+", "many")))
print((("door:open"):gsub("(%a+):(%a+)", "%2 %1")))
print((("3 coins, 12 gems"):gsub("%d+", function(n)
return tonumber(n) * 2
end)))It prints
many coins, many gems
open door
6 coins, 24 gems(The extra brackets round each call keep only the first of the two values gsub gives.)
The signs ( ) . % + - * ? [ ] ^ $ have a meaning in a pattern. To look for one of them as itself, put % before it (%. is a real full stop), or tell find to take the text literally with true as its fourth value:
print(("3.14"):find(".", 1, true))
print(("3.14"):find("%."))It prints
2 2
2 2Letters of every language
A string is kept as bytes, and the letters of many languages take more than one byte each. # and sub count bytes, which is right for plain English text and wrong for most others. The utf8 library counts letters:
local word = "héllo"
print(#word, utf8.len(word))
print(utf8.sub(word, 1, 2))It prints
6 5
héNames of variables can be written in any language's letters, too.
Next: when something goes wrong.