Muster
Mit find und 1, true suchst du nach einem genauen Text. Oft kennst du den Text aber nicht, nur seine Gestalt: „eine Zahl“, „das Wort nach Verkauft“. Dafür hat Lua Muster: Texte, in denen manche Zeichen eine besondere Bedeutung haben. (Viele Sprachen haben dafür reguläre Ausdrücke. Luas Muster sind ihre kleinere, einfachere Verwandte: Wenn du reguläre Ausdrücke kennst, suche hier nicht nach | oder \d.)
Die Methode match gibt den ersten Teil eines Textes zurück, der zu einem Muster passt, oder nil, wenn nichts passt. Die nützlichsten Bausteine eines Musters sind Zeichenklassen, von denen jede für ein Zeichen einer Art steht:
%d: eine Ziffer, 0 bis 9;%a: ein Buchstabe von a bis z, klein oder groß;%w: ein Buchstabe oder eine Ziffer;%s: ein Leerzeichen (oder ein Tabulator oder ein Zeilenumbruch);.: ein beliebiges Zeichen.
Ein Großbuchstabe bedeutet das Gegenteil: %D ist alles außer einer Ziffer, %S alles außer einem Leerzeichen. Nach einer Klasse sagst du, wie viele solche Zeichen du willst: + eines oder mehr, so viele wie möglich; * null oder mehr, so viele wie möglich. Ohne sie steht die Klasse für genau ein Zeichen:
local notiz = "Die Hennen legten 18 Eier"
print(notiz:match("%d+"))
print(notiz:match("%a+"))
print(notiz:match("%d"))
print(notiz:match("%d+%s*%a+"))Das gibt Folgendes aus:
18
Die
1
18 EierLies das letzte Muster als „Ziffern, vielleicht Leerzeichen, Buchstaben“. Das * nach %s erlaubt auch gar kein Leerzeichen, das Muster würde also auch 18Eier finden.
Zwei Zeichen binden ein Muster an die Enden des Textes: ^ am Anfang eines Musters heißt, dass der Treffer am Anfang des Textes beginnen muss, und $ am Ende eines Musters heißt, dass er am Ende des Textes enden muss. Mit beiden muss der ganze Text passen. So prüfst du, ob ein Text eine ganze Zahl ist:
print(("42"):match("^%d+$"))
print(("42 Eier"):match("^%d+$"))Das gibt Folgendes aus:
42
nilMeistens willst du ein paar Teile eines Textes haben, nicht den ganzen Treffer. Setze diese Teile des Musters in Klammern, sogenannte Captures, und match gibt dir nur sie zurück, einen Wert für jedes Klammernpaar:
local eintrag = "Verkauft 24 Eier"
local anzahl, ware = eintrag:match("Verkauft (%d+) (%a+)")
print(ware, anzahl)
print(tonumber(anzahl) * 2)Das gibt Folgendes aus:
Eier 24
48Die Teile außerhalb der Klammern, Verkauft und die Leerzeichen, müssen ebenfalls im Text stehen, werden aber nicht zurückgegeben. Captures sind immer Texte, auch "24", wandle Zahlen also mit tonumber um. Und wenn der Text nicht zum Muster passt, gibt match nur nil zurück, sodass anzahl und ware beide nil sind: Prüfe sie, bevor du sie benutzt.
Zeichen mit besonderer Bedeutung, ( ) . % + - * ? [ ] ^ $, heißen Sonderzeichen (englisch magic characters). Um eines davon als gewöhnliches Zeichen zu finden, setze ein % davor: %. ist ein Punkt, %( eine Klammer:
print(("Preis: 3.50 Münzen"):match("%d+%.%d+"))Das gibt Folgendes aus:
3.50Und noch einmal die Umlaute. %a und %w kennen nur die Buchstaben von a bis z, der Treffer hört also vor dem ersten Umlaut auf:
print(("Gemüse"):match("%a+"))Das gibt Folgendes aus:
GemFür Wörter, die Umlaute haben können, benutze %S+: alle Zeichen bis zum nächsten Leerzeichen (auch Satzzeichen, ein Komma direkt nach einem Wort gehört also dazu).
So schreibst du es:
Anweisungen
- 1
Ersetze das
printin der Schleife: Hole die Anzahl, die Pflanze und die Münzen aus jeder Notiz mit einem einzigenmatchund drei Captures. Erfasse die Pflanze mit%S+, wegen der Umlaute. Die Notiz über den Regen passt nicht zum Muster: Überspringe sie. Gib für jeden Verkauf den Preis für ein Stück aus (teile mit//, damit es eine Ganzzahl ist):12 Kürbisse zu je 20 Münzen 40 Äpfel zu je 2 Münzen - 2
Gib unter der Schleife aus, wie viele Münzen Emma mit allen Verkäufen zusammen eingenommen hat:
Insgesamt: 320 Münzen.