0Pricing
Linux Command Line & Bash Scripting Mastery · Lektion

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 Linux Command Line & Bash Scripting Mastery-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 Linux Command Line & Bash Scripting Mastery-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Linux Command Line & Bash Scripting Mastery-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] = value zu
  • 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. $1 für den Benutzernamen)
  • Wert = die laufende Summe des numerischen Feldes (z. B. $2 fü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 Vorkommen
  • total[key] += $N – erfasst die laufende Summe
  • Teilen Sie in END total[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] oder arr[$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:

  1. awk zählt die Vorkommen in einem Array und gibt in END count key aus
  2. sort -rn sortiert numerisch in absteigender Reihenfolge
  3. head -n 5 behä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 wird
  • FNR == 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 sortieren
  • sort -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 Eintrag
  • delete 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 in END
#!/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, in END ausgeben
  • Summieren: total[$key] += $N – numerische Felder pro Gruppe akkumulieren
  • Durchschnitt: sowohl count[] als auch total[] verwalten und in END teilen
  • 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 END ausgegebene awk-Ausgabe für eine deterministische Reihenfolge durch sort leiten
  • Abschnittsweise Zurücksetzung: mit delete arr den 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 Linux Command Line & Bash Scripting Mastery-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Linux Command Line & Bash Scripting Mastery-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 Linux Command Line & Bash Scripting Mastery 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 Linux Command Line & Bash Scripting Mastery zu starten?

Keine Vorkenntnisse erforderlich. Linux Command Line & Bash Scripting Mastery 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 Linux Command Line & Bash Scripting Mastery-Lektion Code schreiben und ausführen?

Ja. Jede Linux Command Line & Bash Scripting Mastery-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

  1. Datensätze, Felder und benutzerdefinierte Trennzeichen in awk
  2. Muster, Bereiche und BEGIN-/END-Blöcke
  3. Aggregation mit awk-Arrays und Gruppierung
  4. awk-Funktionen, printf-Formatierung und Berichtserstellung
← Zurück zu Linux Command Line & Bash Scripting Mastery