Patterns
With find and 1, true, you search for an exact text. Often, though, you don't know the text, only its shape: “a number”, “the word after Sold”. For that, Lua has patterns: texts in which some characters have a special meaning. (Many languages have regular expressions for this. Lua's patterns are their smaller, simpler cousin: if you know regular expressions, don't look for | or \d here.)
The method match gives the first part of a text that fits a pattern, or nil when nothing fits. The most useful pieces of a pattern are character classes, each of which stands for one character of a kind:
%d: a digit, 0 to 9;%a: a letter from a to z, small or capital;%w: a letter or a digit;%s: a space (or a tab, or a new line);.: any character.
A capital letter means the opposite: %D is anything but a digit, %S anything but a space. After a class, you say how many such characters you want: + one or more, as many as possible; * zero or more, as many as possible. Without them, the class means exactly one character:
local note = "The hens laid 18 eggs"
print(note:match("%d+"))
print(note:match("%a+"))
print(note:match("%d"))
print(note:match("%d+%s*%a+"))This prints:
18
The
1
18 eggsRead the last pattern as “digits, maybe some spaces, letters”. The * after %s allows no space at all, too, so the pattern would also find 18eggs.
Two characters tie a pattern to the ends of the text: ^ at the start of a pattern means the match must start at the beginning of the text, and $ at the end of a pattern means it must end at the end of the text. With both, the whole text has to fit. That's how you check whether a text is a whole number:
print(("42"):match("^%d+$"))
print(("42 eggs"):match("^%d+$"))This prints:
42
nilMost of the time, you want a few parts of a text, not the whole match. Put those parts of the pattern in parentheses, called captures, and match gives you just them, one value for each pair of parentheses:
local entry = "Sold 24 eggs"
local count, item = entry:match("Sold (%d+) (%a+)")
print(item, count)
print(tonumber(count) * 2)This prints:
eggs 24
48The parts outside the parentheses, Sold and the spaces, must be in the text too, but they aren't returned. Captures are always texts, even "24", so turn numbers into numbers with tonumber. And when the text doesn't fit the pattern, match gives just nil, so both count and item are nil: check them before you use them.
Characters with a special meaning, ( ) . % + - * ? [ ] ^ $, are called magic characters. To find one of them as an ordinary character, put a % before it: %. is a period, %( a parenthesis:
print(("Price: 3.50 coins"):match("%d+%.%d+"))This prints:
3.50And the accents again. %a and %w know only the letters from a to z, so the match stops before the first letter with an accent:
print(("jalapeños"):match("%a+"))This prints:
jalapeFor words that may have accents, use %S+: all the characters up to the next space (punctuation too, so a comma right after a word becomes part of it).
Instructions
Replace the print in the loop: get the number, the crop and the coins from each note with one match and three captures. Capture the crop with %S+, because of the ñ. The note about the rain doesn't fit the pattern: skip it. For each sale, print the price of one piece (divide with //, so that it's a whole number):
12 pumpkins at 20 coins each
40 jalapeños at 2 coins eachBelow the loop, print how many coins Emma got from all the sales together: Total: 320 coins.
Start programming for free
6/9