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.
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.
$1for brugernavn) - Værdi = den løbende total for det numeriske felt (f.eks.
$2for 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å forekomstertotal[key] += $N— holder styr på den løbende sum- I
ENDdividerer dutotal[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]ellerarr[$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:
- awk tæller forekomster i en array og udskriver
count keyiEND sort -rnsorterer numerisk i faldende rækkefølgehead -n 5beholder 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 øjeblikketFNR == 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) alfabetisksort -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 postdelete 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:
vhostudtrukket fra et felt - Parallelle arrays:
reqs[],bytes[],errors[] - Betinget akkumulering:
$9 >= 400for kun at tælle fejlsvar - Formateret
printf-tabel iEND
#!/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 iEND - Summering:
total[$key] += $N— akkumulér numeriske felter pr. gruppe - Gennemsnit: vedligehold både
count[]ogtotal[], og divider iEND - 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 gennemsortfor deterministisk rækkefølge - Nulstilling af sektioner: brug
delete arrtil 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.
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
- Poster, felter og brugerdefinerede separatorer i awk
- Mønstre, områder og BEGIN/END-blokke
- Aggregering med awk-arrays og gruppering
- awk-funktioner, printf-formatering og rapportgenerering