Aggregazione con array e raggruppamenti in awk
Calcoli somme, conteggi e riepiloghi raggruppati per campo usando array associativi indicizzati dai valori dei campi.
Aggregazione con array e raggruppamenti in awk è una lezione DevOps Bootcamp gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento DevOps Bootcamp, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso DevOps Bootcamp include 4 lezioni in totale.
Cosa sono gli array associativi di awk?
In awk, un array associativo è una struttura chiave-valore in cui le chiavi possono essere stringhe o numeri. A differenza degli array indicizzati della maggior parte dei linguaggi, gli array di awk sono in realtà tabelle hash: sono perfetti per raggruppare e aggregare i dati in base ai valori dei campi.
- Dichiarazione implicita: basta assegnare
arr[key] = value - Le chiavi sono stringhe per impostazione predefinita (i numeri vengono convertiti)
- Nessun limite di dimensione: awk espande l'array secondo necessità
- Ideali per calcolare somme, conteggi e raggruppamenti aggregati in un'unica passata
Non è necessario inizializzare una chiave prima di incrementarla: awk considera automaticamente una chiave non impostata come zero o come stringa vuota.
Conteggio delle righe per gruppo
Il pattern di aggregazione più comune consiste nel contare quante volte compare ogni valore univoco di un campo. Utilizzi il campo $1 (o qualsiasi altro campo) come chiave dell'array e incrementi un contatore per ogni riga corrispondente.
Il blocco END viene eseguito dopo aver consumato tutti i dati in input: è qui che stampa i risultati accumulati.
count[$1]++Dopo l'elaborazione, count contiene il numero totale di righe per ogni valore univoco di $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]
}'
Somma di un campo numerico per gruppo
Il conteggio è solo una forma di aggregazione. Per sommare un campo numerico raggruppandolo in base a un altro campo, accumuli il valore numerico in un array indicizzato dal campo del gruppo.
Il pattern è il seguente:
- Chiave = il campo usato per il raggruppamento (ad esempio
$1per il nome utente) - Valore = il totale progressivo del campo numerico (ad esempio
$2per i byte)
In questo modo calcola la somma completa per gruppo in un'unica passata di awk, senza bisogno di ordinamento o pre-elaborazione.
#!/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]
}'
Combinazione di conteggio e somma in un'unica passata
awk consente di gestire più array contemporaneamente, fornendo conteggio e somma (e quindi anche la media) per ogni gruppo in un'unica scansione del file. È molto più efficiente che eseguire due volte la pipeline.
count[key]++— tiene traccia delle occorrenzetotal[key] += $N— tiene traccia della somma progressiva- In
END, dividatotal[k] / count[k]per ottenere la media del gruppo
#!/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]
}'
Chiavi composte da più campi per il raggruppamento bidimensionale
È possibile creare una chiave composta concatenando più campi con un separatore. In questo modo si ottiene un raggruppamento su due dimensioni senza alcuna sintassi speciale.
Scelga un separatore che non possa comparire nei dati (ad esempio SUBSEP, il separatore di record integrato di awk \034, oppure una barra verticale letterale |).
- Chiave composta:
arr[$1 SUBSEP $2]oppurearr[$1"|"$2] - Divida nuovamente la chiave durante la stampa:
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]
}
}'
Rilevamento del minimo e del massimo per gruppo
Gli array associativi facilitano il rilevamento dei valori min e max per gruppo. Il trucco consiste nell'inizializzare il valore solo alla prima occorrenza di ogni chiave, usando la condizione speciale !(key in arr).
!(key in min_arr)è vera la prima volta che viene rilevata una chiave- Dopo l'inizializzazione, confronti e sovrascriva il valore con il normale controllo minore di / maggiore di
Questo pattern evita uno zero spurio che falserebbe il valore minimo.
#!/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]
}'
Distribuzione delle frequenze — gruppi Top-N
Un'attività comune nel mondo reale consiste nel trovare i valori più frequenti, fino a N. awk gestisce il conteggio; utilizzi sort e head in una pipeline per ordinare e limitare i risultati.
Questo pattern di pipeline è idiomatico nella gestione delle shell:
- awk conta le occorrenze in un array e stampa
count keyinEND sort -rnordina numericamente in ordine decrescentehead -n 5conserva solo i primi 5 risultati
Lasciare ad awk il compito di aggregare e delegare l'ordinamento a sort segue la filosofia Unix.
#!/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
Utilizzo di NR e FNR per l'aggregazione su più file
Durante l'elaborazione di più file, le variabili integrate di awk NR (numero totale di record letti) e FNR (numero di record nel file corrente) consentono di indicare da quale file proviene ogni record usando FILENAME.
FILENAME— nome del file attualmente in letturaFNR == 1— si attiva all'inizio di ogni nuovo file (utile per saltare le intestazioni)
Questo consente di eseguire aggregazioni per gruppo e per file sull'intero contenuto di una directory di log con una sola invocazione di awk.
Stampa dell'output ordinato dagli array di awk
Il ciclo for (key in array) di awk non garantisce l'ordine. Per ottenere un output deterministico, passi a sort la stampa del blocco END di awk oppure raccolga i valori e li ordini all'interno di awk usando le funzioni asorti / asort (solo GNU awk).
Per gli script multipiattaforma, di solito si preferisce l'approccio portabile basato su una pipeline della shell:
sort -k1,1— ordina alfabeticamente in base al primo campo (la chiave del gruppo)sort -k2,2rn— ordina in base al secondo campo (conteggio/somma) numericamente in ordine decrescente
#!/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
Eliminazione delle chiavi degli array e azzeramento dello stato
A volte è necessario reimpostare lo stato dell'aggregazione durante l'elaborazione, ad esempio quando si elaborano file di log in cui ogni sezione è separata da una riga vuota o da un valore sentinella.
delete arr[key]— rimuove una singola vocedelete arr— cancella l'intero array (GNU awk)- Verifichi l'esistenza con
(key in arr)prima di accedere all'array, per evitare di creare voci fantasma
Questa tecnica consente di eseguire aggregazioni su una finestra scorrevole o per sezione senza riavviare 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
}'
Pipeline reale: riepilogo dei log Nginx
Mettiamo insieme tutti gli elementi: ecco un'aggregazione awk di livello produttivo, eseguita in un'unica passata sul formato di log combinato di Nginx. Calcola numero di richieste, byte totali e tasso di errore per host virtuale in un'unica scansione.
Tecniche principali utilizzate:
- Chiave composta:
vhostestratto da un campo - Array paralleli:
reqs[],bytes[],errors[] - Accumulo condizionale:
$9 >= 400per contare solo le risposte di errore - Tabella formattata con
printfinEND
#!/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
}'
Verifica delle conoscenze: inizializzazione corretta del minimo
Verifichi la sua comprensione di un errore comune nell'aggregazione con awk.
Riepilogo della lezione: aggregazione con gli array di awk
Ha appreso i pattern fondamentali per calcolare aggregazioni per gruppo interamente all'interno di awk:
- Conteggio:
count[$key]++— incrementare a ogni riga e stampare inEND - Somma:
total[$key] += $N— accumulare i campi numerici per gruppo - Media: mantenere sia
count[]siatotal[]e dividere inEND - Minimo/Massimo: inizializzare alla prima occorrenza usando
!(key in arr), quindi confrontare - Chiavi composte: concatenare i campi con un separatore per il raggruppamento su più dimensioni
- Output ordinato: passare a
sortla stampa del bloccoENDdi awk per ottenere un ordinamento deterministico - Reimpostazione delle sezioni: usare
delete arrper cancellare lo stato tra sezioni logiche dell'input
Questi pattern consentono di sostituire query di database complesse o più passate nella pipeline con una singola invocazione efficiente di awk: una competenza essenziale per l'ingegneria delle shell in produzione.
Domande Frequenti
La lezione «Aggregazione con array e raggruppamenti in awk» è gratuita?
Sì — il testo completo di «Aggregazione con array e raggruppamenti in awk» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso DevOps Bootcamp, passa a CoddyKit PRO. Il corso DevOps Bootcamp include 4 lezioni in totale.
Cosa imparerò in «Aggregazione con array e raggruppamenti in awk»?
Calcoli somme, conteggi e riepiloghi raggruppati per campo usando array associativi indicizzati dai valori dei campi. Eserciti DevOps Bootcamp con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare DevOps Bootcamp?
Non è richiesta alcuna esperienza precedente. DevOps Bootcamp su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Aggregazione con array e raggruppamenti in awk»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione DevOps Bootcamp?
Sì. Ogni lezione DevOps Bootcamp include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Record, campi e separatori personalizzati in awk
- Pattern, intervalli e blocchi BEGIN/END
- Aggregazione con array e raggruppamenti in awk
- Funzioni awk, formattazione con printf e generazione di report