Intensiv DevOps-uddannelse · Lektion

Aggregering med awk-arrays og gruppering

Beregn summer, antal og grupperede oversigter ved hjælp af associative arrays med felternes værdier som nøgler.

Lektion 3 af 413 trin

Aggregering med awk-arrays og gruppering er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Intensiv DevOps-uddannelse, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.

Hvad er associative arrays i awk?

I awk er en associativ array et lager med nøgler og værdier, hvor nøglerne kan være en vilkårlig streng eller et tal. I modsætning til indekserede arrays i de fleste sprog er awk-arrays i praksis hash-tabeller — perfekte til at gruppere og aggregere data efter feltværdier.

  • Deklareres implicit: tildel blot arr[key] = value
  • Nøgler er som standard strenge (tal konverteres)
  • Ingen størrelsesgrænse — awk udvider arrayen efter behov
  • Ideelle til at beregne summer, antal og grupperede opsummeringer i én gennemgang

Du behøver ikke initialisere en nøgle, før du øger dens værdi — awk behandler automatisk en nøgle, der ikke er sat, som nul eller en tom streng.

Optælling af linjer pr. gruppe

Det mest almindelige aggregeringsmønster er at tælle, hvor mange gange hver unik værdi i et felt forekommer. Brug feltet $1 (eller et hvilket som helst andet felt) som arrayets nøgle, og øg en tæller for hver matchende række.

Blokken END køres, efter at alt input er læst — det er her, du udskriver de opsamlede resultater.

count[$1]++

Efter behandlingen indeholder count det samlede antal linjer for hver unik værdi af $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]
}'

Summering af et numerisk felt pr. gruppe

Optælling er kun én form for aggregering. Hvis du vil summere et numerisk felt grupperet efter et andet felt, skal du akkumulere den numeriske værdi i en array, der bruger gruppefeltet som nøgle.

Mønsteret er:

  • Nøgle = feltet, der bruges til gruppering (f.eks. $1 for brugernavn)
  • Værdi = den løbende total for det numeriske felt (f.eks. $2 for bytes)

Dette beregner en komplet grupperet sum i én awk-gennemgang — sortering eller forbehandling er ikke nødvendig.

#!/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]
}'

Kombination af optælling og summering i én gennemgang

awk lader dig vedligeholde flere arrays samtidigt, så du kan beregne antal og sum (og dermed gennemsnit) for hver gruppe i én gennemgang af filen. Det er langt mere effektivt end at køre datakæden to gange.

  • count[key]++ — holder styr på forekomster
  • total[key] += $N — holder styr på den løbende sum
  • I END dividerer du total[k] / count[k] for at få gennemsnittet pr. gruppe
#!/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]
}'

Nøgler med flere felter til 2D-gruppering

Du kan oprette en sammensat nøgle ved at sammenkæde flere felter med et skilletegn. Det giver dig en todimensionel gruppering uden særlig syntaks.

Vælg et skilletegn, der ikke kan forekomme i dataene (f.eks. SUBSEP, det indbyggede awk-postskilletegn \034 eller en bogstavelig lodret streg |).

  • Sammensat nøgle: arr[$1 SUBSEP $2] eller arr[$1"|"$2]
  • Opdel nøglen igen under udskrivning: 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]
    }
}'

Sporing af minimum og maksimum pr. gruppe

Associative arrays gør det nemt at spore min- og max-værdier pr. gruppe. Tricket er kun at initialisere ved den første forekomst af hver nøgle ved hjælp af den særlige betingelse !(key in arr).

  • !(key in min_arr) er sand første gang, en nøgle ses
  • Efter initialiseringen sammenligner du og overskriver med det almindelige tjek for mindre end / større end

Dette mønster undgår et misvisende nul, som ellers ville ødelægge din minimumsværdi.

#!/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]
}'

Frekvensfordeling — top-N-grupper

En almindelig opgave fra virkeligheden er at finde de N hyppigst forekommende værdier. awk håndterer optællingen; send resultatet gennem sort og head for at rangordne og begrænse det.

Dette datakædemønster er idiomatisk i shell-udvikling:

  1. awk tæller forekomster i en array og udskriver count key i END
  2. sort -rn sorterer numerisk i faldende rækkefølge
  3. head -n 5 beholder kun de 5 øverste

Ved at lade awk fokusere på aggregering og overlade sorteringen til sort følger du Unix-filosofien.

#!/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

Brug af NR og FNR til aggregering på tværs af filer

Når du behandler flere filer, kan awks indbyggede NR (det samlede antal læste poster) og FNR (poster i den aktuelle fil) sammen med FILENAME fortælle, hvilken fil hver post kom fra.

  • FILENAME — navnet på den fil, der læses i øjeblikket
  • FNR == 1 — udløses ved starten af hver ny fil (nyttigt til at springe overskrifter over)

Det gør det muligt at aggregere grupper pr. fil på tværs af en hel mappe med logfiler i én awk-påkaldelse.

Udskrivning af sorteret output fra awk-arrays

Løkken for (key in array) i awk garanterer ikke nogen rækkefølge. Hvis du vil have deterministisk output, kan du sende awks END-udskrivning gennem sort eller samle værdierne og sortere dem i awk ved hjælp af funktionerne asorti / asort (kun GNU awk).

Den portable shell-datakædetilgang foretrækkes normalt til scripts på tværs af platforme:

  • sort -k1,1 — sortér efter det første felt (gruppenøgle) alfabetisk
  • sort -k2,2rn — sortér efter det andet felt (antal/sum) numerisk i faldende rækkefølge
#!/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

Sletning af arraynøgler og nulstilling af tilstand

Nogle gange skal du nulstille aggregeringstilstanden undervejs — f.eks. når du behandler logfiler, hvor hver sektion er adskilt af en tom linje eller en markørværdi.

  • delete arr[key] — fjerner en enkelt post
  • delete arr — rydder hele arrayen (GNU awk)
  • Kontrollér, om nøglen findes, med (key in arr), før du tilgår den, for at undgå at oprette spøgelsesposter

Denne teknik gør det muligt at aggregere med skydevindue eller pr. sektion uden at genstarte awk.

#!/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
}'

Datakæde fra virkeligheden: opsummering af Nginx-log

Her samler vi det hele — en produktionsklar awk-aggregering i én gennemgang af et Nginx-logformat med kombinerede felter. Den beregner antal forespørgsler, samlet antal bytes og fejlfrekvens pr. virtuel vært i én gennemgang.

Anvendte nøgleteknikker:

  • Sammensat nøgle: vhost udtrukket fra et felt
  • Parallelle arrays: reqs[], bytes[], errors[]
  • Betinget akkumulering: $9 >= 400 for kun at tælle fejlsvar
  • Formateret printf-tabel i 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
}'

Videnstjek: Korrekt initialisering af minimum

Test din forståelse af en almindelig faldgrube ved aggregering i awk.

Opsummering af lektionen: Aggregering med awk-arrays

Du har lært de grundlæggende mønstre til at beregne grupperede aggregeringer udelukkende i awk:

  • Optælling: count[$key]++ — øg ved hver række, og udskriv i END
  • Summering: total[$key] += $N — akkumulér numeriske felter pr. gruppe
  • Gennemsnit: vedligehold både count[] og total[], og divider i END
  • Min./maks.: initialisér ved den første forekomst med !(key in arr), og sammenlign derefter
  • Sammensatte nøgler: sammenkæd felter med et skilletegn for flerdimensionel gruppering
  • Sorteret output: send awks END-udskrivning gennem sort for deterministisk rækkefølge
  • Nulstilling af sektioner: brug delete arr til at rydde tilstanden mellem logiske sektioner i inputtet

Disse mønstre lader dig erstatte tunge databaseforespørgsler eller flere gennemløb af datakæden med én effektiv awk-påkaldelse — en vigtig færdighed inden for produktionsklar shell-udvikling.

Gratis at komme i gang

Lær Intensiv DevOps-uddannelse med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
142
Lektioner
568

Ofte stillede spørgsmål

Er lektionen “Aggregering med awk-arrays og gruppering” gratis?

Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Aggregering med awk-arrays og gruppering”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Aggregering med awk-arrays og gruppering”?

Beregn summer, antal og grupperede oversigter ved hjælp af associative arrays med felternes værdier som nøgler. Du øver dig i Intensiv DevOps-uddannelse med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Intensiv DevOps-uddannelse?

Der kræves ingen tidligere erfaring. Intensiv DevOps-uddannelse på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Aggregering med awk-arrays og gruppering”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Intensiv DevOps-uddannelse-lektion?

Ja. Alle Intensiv DevOps-uddannelse-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Poster, felter og brugerdefinerede separatorer i awk
  2. Mønstre, områder og BEGIN/END-blokke
  3. Aggregering med awk-arrays og gruppering
  4. awk-funktioner, printf-formatering og rapportgenerering
← Tilbage til Intensiv DevOps-uddannelse