Aggregation mit awk-Arrays und Gruppierung
Berechnen Sie Summen, Anzahlen und Gruppierungen mithilfe assoziativer Arrays, deren Schlüssel aus Feldwerten bestehen.
Aggregation mit awk-Arrays und Gruppierung ist eine kostenlose DevOps Bootcamp-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des DevOps Bootcamp-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der DevOps Bootcamp-Kurs umfasst insgesamt 4 Lektionen.
Was sind assoziative Arrays in awk
In awk ist ein assoziatives Array ein Schlüssel-Wert-Speicher, dessen Schlüssel beliebige Zeichenketten oder Zahlen sein können. Im Gegensatz zu indizierten Arrays in den meisten Sprachen sind awk-Arrays intern Hashmaps – ideal, um Daten anhand von Feldwerten zu gruppieren und zu aggregieren.
- Implizit deklarieren: Weisen Sie einfach
arr[key] = valuezu - Schlüssel sind standardmäßig Zeichenketten (Zahlen werden konvertiert)
- Keine Größenbegrenzung – awk vergrößert das Array bei Bedarf
- Ideal zum Berechnen von Summen, Anzahlen und Group-by-Auswertungen in einem einzigen Durchlauf
Sie müssen einen Schlüssel vor dem Inkrementieren nicht initialisieren – awk behandelt einen nicht gesetzten Schlüssel automatisch als null oder als leere Zeichenkette.
Zeilen pro Gruppe zählen
Das häufigste Aggregationsmuster besteht darin, zu zählen, wie oft jeder eindeutige Wert eines Feldes vorkommt. Verwenden Sie das Feld $1 (oder ein beliebiges anderes Feld) als Array-Schlüssel und erhöhen Sie bei jeder passenden Zeile einen Zähler.
Der END-Block wird ausgeführt, nachdem alle Eingaben verarbeitet wurden – dort geben Sie die gesammelten Ergebnisse aus.
count[$1]++Nach der Verarbeitung enthält count die Gesamtzahl der Zeilen für jeden eindeutigen Wert von $1.
#!/usr/bin/env bash
# Count how many log entries exist per HTTP status code
# Input format: <ip> <date> <method> <path> <status> <bytes>
printf '10.0.0.1 2024-01-01 GET /index 200 512
10.0.0.2 2024-01-01 POST /api 404 128
10.0.0.3 2024-01-01 GET /img 200 2048
10.0.0.4 2024-01-01 GET /api 500 64
10.0.0.5 2024-01-01 DELETE /api 404 32
' | awk '
{
count[$5]++
}
END {
for (status in count)
print status, count[status]
}'
Numerisches Feld pro Gruppe summieren
Zählen ist nur eine Form der Aggregation. Um ein numerisches Feld nach einem anderen Feld gruppiert zu summieren, akkumulieren Sie den numerischen Wert in einem Array, dessen Schlüssel das Gruppenfeld ist.
Das Muster lautet:
- Schlüssel = das Group-by-Feld (z. B.
$1für den Benutzernamen) - Wert = die laufende Summe des numerischen Feldes (z. B.
$2für Bytes)
Damit berechnen Sie eine vollständige Group-by-Summe in einem einzigen awk-Durchlauf – Sortieren oder Vorverarbeiten ist nicht erforderlich.
#!/usr/bin/env bash
# Sum bytes transferred per user from an access log
printf 'alice 1024
bob 512
alice 2048
charlie 256
bob 768
alice 128
' | awk '
{
bytes[$1] += $2
}
END {
for (user in bytes)
printf "%-10s %d bytes\n", user, bytes[user]
}'
Anzahl und Summe in einem Durchlauf kombinieren
Mit awk können Sie mehrere Arrays gleichzeitig verwalten und so für jede Gruppe bei einem einzigen Durchlauf durch die Datei Anzahl und Summe (und damit auch den Durchschnitt) ermitteln. Das ist wesentlich effizienter, als die Pipeline zweimal auszuführen.
count[key]++– erfasst die Vorkommentotal[key] += $N– erfasst die laufende Summe- Teilen Sie in
ENDtotal[k] / count[k], um den Durchschnitt pro Gruppe zu berechnen
#!/usr/bin/env bash
# Compute per-department headcount and average salary
printf 'Engineering Alice 95000
Engineering Bob 88000
Marketing Carol 72000
Marketing Dave 68000
Engineering Eve 102000
Marketing Frank 75000
' | awk '
{
dept = $1
sal = $3
count[dept]++
total[dept] += sal
}
END {
printf "%-15s %5s %10s\n", "Department", "Count", "Avg Salary"
for (d in count)
printf "%-15s %5d %10.0f\n", d, count[d], total[d]/count[d]
}'
Mehrfeldschlüssel für zweidimensionale Gruppierung
Sie können einen zusammengesetzten Schlüssel erstellen, indem Sie mehrere Felder mit einem Trennzeichen verketten. Damit erhalten Sie ein zweidimensionales Group-by ohne spezielle Syntax.
Wählen Sie ein Trennzeichen, das in den Daten nicht vorkommen kann (z. B. SUBSEP, das integrierte awk-Datensatztrennzeichen \034 oder einen literalen senkrechten Strich |).
- Zusammengesetzter Schlüssel:
arr[$1 SUBSEP $2]oderarr[$1"|"$2] - Schlüssel bei der Ausgabe wieder aufteilen:
split(key, parts, "|")
#!/usr/bin/env bash
# Count requests grouped by HTTP method AND status code
printf 'GET 200
POST 201
GET 404
GET 200
DELETE 204
POST 201
GET 404
POST 500
' | awk '
{
key = $1 "|" $2
count[key]++
}
END {
printf "%-8s %-6s %s\n", "Method", "Status", "Count"
for (k in count) {
split(k, parts, "|")
printf "%-8s %-6s %d\n", parts[1], parts[2], count[k]
}
}'
Minimum und Maximum pro Gruppe erfassen
Mit assoziativen Arrays lassen sich min- und max-Werte pro Gruppe einfach erfassen. Der entscheidende Trick besteht darin, nur beim ersten Auftreten jedes Schlüssels zu initialisieren, und zwar mit der speziellen Bedingung !(key in arr).
!(key in min_arr)ist beim ersten Auftreten eines Schlüssels wahr- Vergleichen und überschreiben Sie nach der Initialisierung mit der üblichen Prüfung auf kleiner bzw. größer
Dieses Muster verhindert eine fälschlich gesetzte Null, die Ihr Minimum verfälschen würde.
#!/usr/bin/env bash
# Find min and max response time per endpoint
printf '/api/users 120
/api/orders 340
/api/users 98
/api/orders 512
/api/users 210
/api/orders 280
/health 5
/health 7
' | awk '
{
ep = $1
rt = $2
if (!(ep in mn)) { mn[ep] = rt; mx[ep] = rt }
if (rt < mn[ep]) mn[ep] = rt
if (rt > mx[ep]) mx[ep] = rt
}
END {
printf "%-15s %6s %6s\n", "Endpoint", "Min", "Max"
for (ep in mn)
printf "%-15s %6d %6d\n", ep, mn[ep], mx[ep]
}'
Häufigkeitsverteilung – Top-N-Gruppen
Eine häufige Aufgabe aus der Praxis besteht darin, die N am häufigsten vorkommenden Werte zu ermitteln. awk übernimmt das Zählen; leiten Sie die Ausgabe durch sort und head, um sie zu sortieren und zu begrenzen.
Dieses Pipeline-Muster ist in der Shell-Entwicklung idiomatisch:
- awk zählt die Vorkommen in einem Array und gibt in
ENDcount keyaus sort -rnsortiert numerisch in absteigender Reihenfolgehead -n 5behält nur die Top 5
Wenn Sie awk auf die Aggregation konzentrieren und das Sortieren an sort delegieren, folgen Sie der Unix-Philosophie.
#!/usr/bin/env bash
# Top 3 most active IP addresses from an access log
printf '192.168.1.10 GET /index
10.0.0.5 POST /api
192.168.1.10 GET /css
172.16.0.3 GET /index
10.0.0.5 GET /api
192.168.1.10 DELETE /api
172.16.0.3 POST /login
10.0.0.5 GET /index
10.0.0.5 POST /logout
' | awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' \
| sort -rn \
| head -n 3
NR und FNR für die Aggregation über mehrere Dateien verwenden
Bei der Verarbeitung mehrerer Dateien können Sie mit den integrierten Variablen NR (insgesamt gelesene Datensätze) und FNR (Datensätze in der aktuellen Datei) mithilfe von FILENAME kennzeichnen, aus welcher Datei jeder Datensatz stammt.
FILENAME– Name der Datei, die gerade gelesen wirdFNR == 1– wird am Anfang jeder neuen Datei ausgelöst (nützlich zum Überspringen von Kopfzeilen)
So können Sie in einem einzigen awk-Aufruf Group-by-Aggregationen über ein gesamtes Verzeichnis mit Protokolldateien hinweg durchführen.
Sortierte Ausgabe aus awk-Arrays ausgeben
Die Schleife for (key in array) in awk garantiert keine Reihenfolge. Für eine deterministische Ausgabe leiten Sie die von awk im END-Block ausgegebene Ausgabe durch sort oder sammeln und sortieren Sie die Werte innerhalb von awk mit den Funktionen asorti / asort (nur GNU awk).
Für plattformübergreifende Skripte wird normalerweise der portable Shell-Pipeline-Ansatz bevorzugt:
sort -k1,1– nach dem ersten Feld (Gruppenschlüssel) alphabetisch sortierensort -k2,2rn– nach dem zweiten Feld (Anzahl/Summe) numerisch absteigend sortieren
#!/usr/bin/env bash
# Bytes per user, sorted alphabetically by username
printf 'zara 800
alice 1500
bob 300
alice 200
zara 400
bob 1100
' | awk '
{
total[$1] += $2
}
END {
for (u in total)
print u, total[u]
}' | sort -k1,1
Array-Schlüssel löschen und Zustand zurücksetzen
Manchmal müssen Sie den Aggregationszustand während der Verarbeitung zurücksetzen – zum Beispiel beim Verarbeiten von Protokolldateien, deren Abschnitte durch eine Leerzeile oder einen Signalwert getrennt sind.
delete arr[key]– entfernt einen einzelnen Eintragdelete arr– leert das gesamte Array (GNU awk)- Prüfen Sie mit
(key in arr), ob ein Schlüssel vorhanden ist, bevor Sie darauf zugreifen, um Geistereinträge zu vermeiden
Mit dieser Technik können Sie Gleitfenster- oder abschnittsweise Aggregationen durchführen, ohne awk neu zu starten.
#!/usr/bin/env bash
# Sum values within each section delimited by "---"
printf 'alice 100
bob 200
---
alice 50
bob 75
charlie 300
---
' | awk '
/^---/ {
print "-- Section totals --"
for (u in total) printf " %-10s %d\n", u, total[u]
delete total
next
}
{
total[$1] += $2
}'
Praxis-Pipeline: Nginx-Protokollzusammenfassung
Hier wird alles zusammengeführt: eine produktionsreife Aggregation in einem awk-Durchlauf über das kombinierte Nginx-Logformat. Dabei werden Anzahl der Anfragen, Gesamtzahl der Bytes und Fehlerquote pro virtuellem Host in einem einzigen Durchlauf berechnet.
Verwendete Schlüsseltechniken:
- Zusammengesetzter Schlüssel:
vhost, aus einem Feld extrahiert - Parallele Arrays:
reqs[],bytes[],errors[] - Bedingte Akkumulation:
$9 >= 400, um nur Fehlerantworten zu zählen - Formatierte
printf-Tabelle inEND
#!/usr/bin/env bash
# Simulated Nginx combined log: host ip - - [date] "METHOD /path HTTP/1.1" status bytes
printf 'api.example.com 10.0.0.1 - - [01/Jan/2024] "GET /v1" 200 1024
www.example.com 10.0.0.2 - - [01/Jan/2024] "GET /" 200 4096
api.example.com 10.0.0.3 - - [01/Jan/2024] "POST /v1" 500 128
www.example.com 10.0.0.4 - - [01/Jan/2024] "GET /img" 404 64
api.example.com 10.0.0.5 - - [01/Jan/2024] "GET /v1" 200 2048
www.example.com 10.0.0.6 - - [01/Jan/2024] "GET /" 200 4096
api.example.com 10.0.0.7 - - [01/Jan/2024] "DELETE /v1" 403 32
' | awk '
{
host = $1; status = $9; b = $10
reqs[host]++
bytes[host] += b
if (status + 0 >= 400) errors[host]++
}
END {
printf "%-20s %6s %10s %6s\n", "Host", "Reqs", "Bytes", "Errors"
for (h in reqs)
printf "%-20s %6d %10d %6d\n", h, reqs[h], bytes[h], errors[h]+0
}'
Wissenscheck: Minimum korrekt initialisieren
Testen Sie Ihr Verständnis eines häufigen Problems bei der Aggregation mit awk.
Lektionsrückblick: Aggregation mit awk-Arrays
Sie haben die grundlegenden Muster kennengelernt, um Group-by-Aggregationen vollständig innerhalb von awk zu berechnen:
- Zählen:
count[$key]++– bei jeder Zeile erhöhen, inENDausgeben - Summieren:
total[$key] += $N– numerische Felder pro Gruppe akkumulieren - Durchschnitt: sowohl
count[]als auchtotal[]verwalten und inENDteilen - Minimum/Maximum: beim ersten Auftreten mit
!(key in arr)initialisieren und anschließend vergleichen - Zusammengesetzte Schlüssel: Felder mit einem Trennzeichen für mehrdimensionale Gruppierungen verketten
- Sortierte Ausgabe: die in
ENDausgegebene awk-Ausgabe für eine deterministische Reihenfolge durchsortleiten - Abschnittsweise Zurücksetzung: mit
delete arrden Zustand zwischen logischen Eingabeabschnitten leeren
Mit diesen Mustern können Sie aufwendige Datenbankabfragen oder mehrere Pipeline-Durchläufe durch einen einzigen effizienten awk-Aufruf ersetzen – eine unverzichtbare Fähigkeit für die Shell-Entwicklung im Produktionseinsatz.
Häufig gestellte Fragen
Ist die Lektion „Aggregation mit awk-Arrays und Gruppierung“ kostenlos?
Ja — der vollständige Text von „Aggregation mit awk-Arrays und Gruppierung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des DevOps Bootcamp-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der DevOps Bootcamp-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Aggregation mit awk-Arrays und Gruppierung“?
Berechnen Sie Summen, Anzahlen und Gruppierungen mithilfe assoziativer Arrays, deren Schlüssel aus Feldwerten bestehen. Du übst DevOps Bootcamp mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um DevOps Bootcamp zu starten?
Keine Vorkenntnisse erforderlich. DevOps Bootcamp auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Aggregation mit awk-Arrays und Gruppierung“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser DevOps Bootcamp-Lektion Code schreiben und ausführen?
Ja. Jede DevOps Bootcamp-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Datensätze, Felder und benutzerdefinierte Trennzeichen in awk
- Muster, Bereiche und BEGIN-/END-Blöcke
- Aggregation mit awk-Arrays und Gruppierung
- awk-Funktionen, printf-Formatierung und Berichtserstellung