Über Treffer iterieren
match findet nur den ersten Treffer. Um alle durchzugehen, benutze gmatch (das g steht für global, überall) in einer for-Schleife, so wie ipairs. Bei jedem Durchlauf bekommt die Schleife den nächsten Teil des Textes, der zum Muster passt:
local eier = "Eier diese Woche: 12 9 14 11"
local summe = 0
for zahl in eier:gmatch("%d+") do
summe = summe + tonumber(zahl)
end
print("Gesamt: " .. summe)Das gibt Folgendes aus:
Gesamt: 46Hat das Muster Captures, hat die Schleife für jede eine Variable:
local lager = "Karotten=24,Kartoffeln=8,Tomaten=3"
for name, anzahl in lager:gmatch("(%a+)=(%d+)") do
print(name .. ": " .. anzahl)
endDas gibt Folgendes aus:
Karotten: 24
Kartoffeln: 8
Tomaten: 3gmatch selbst gibt die Treffer nicht zurück; es gibt eine Funktion zurück, die die for-Schleife für den nächsten Treffer aufruft. Es ergibt also nur in einer Schleife Sinn: print(lager:gmatch("%d+")) gibt nur function: 0x… aus, die Adresse dieser Funktion.
Zwei weitere Bausteine von Mustern sind hier praktisch. Eine Menge in eckigen Klammern steht für ein Zeichen aus einer Liste: [aeiou] ist ein Vokal, [%d.] eine Ziffer oder ein Punkt (Klassen funktionieren auch in einer Menge). Mit einem ^ am Anfang bedeutet eine Menge das Gegenteil: [^,] ist jedes Zeichen außer einem Komma. [^,]+ heißt also „alles bis zum nächsten Komma“, der übliche Weg, eine Liste von Werten zu zerlegen:
local pflanzen = "Karotten,Kartoffeln,Grüne Bohnen"
for pflanze in pflanzen:gmatch("[^,]+") do
print(pflanze)
endDas gibt Folgendes aus:
Karotten
Kartoffeln
Grüne BohnenAnders als %a+ hat die Menge kein Problem mit dem Leerzeichen und dem Umlaut in „Grüne Bohnen“. Sieh dir an, was %a+ mit einem Umlaut in so einer Liste macht. Es endet nicht mit einem Fehler, es findet stillschweigend etwas anderes:
local lager = "Karotten=24,Äpfel=5"
for name, anzahl in lager:gmatch("(%a+)=(%d+)") do
print(name .. ": " .. anzahl)
endDas gibt Folgendes aus:
Karotten: 24
pfel: 5Das Ä ist für %a kein Buchstabe, deshalb nahm das Muster nur die Buchstaben danach, pfel, und nichts warnt dich.
Und das letzte Zeichen für Wiederholungen: -, null oder mehr, aber so wenige wie möglich. .* nimmt, so viel es kann, .- hört auf, sobald der Rest des Musters passt. Den Unterschied siehst du bei einem Text zwischen zwei Markierungen:
local text = "Hugo (Händler) und Josef (Nachbar)"
print(text:match("%((.*)%)"))
for rolle in text:gmatch("%((.-)%)") do
print(rolle)
endDas gibt Folgendes aus:
Händler) und Josef (Nachbar
Händler
Nachbar%( und %) sind die Klammern im Text, und die Klammern ohne % sind das Capture. Mit .* reicht das Capture von der ersten öffnenden bis zur letzten schließenden Klammer; mit .- nur bis zur nächsten.
So schreibst du es:
Anweisungen
- 1
Gehe die Bestellung mit
gmatchdurch und gib jede Position in einer eigenen Zeile aus. Benutze für den Namen eine Menge, damit dasÄkein Problem ist:Karotten: 30 Kartoffeln: 12 Äpfel: 40 - 2
Schlage den Preis jeder Position in
preisenach und addiere, wie viel Hugo zahlt: die Stückzahl mal den Preis, für jede Position. Gib unter der SchleifeHugo zahlt 326 Münzenaus. (Der Schlüssel["Äpfel"]steht in eckigen Klammern, weil ein Name mit Umlaut nicht ohne Anführungszeichen geschrieben werden kann.)