Agregowanie za pomocą tablic i grupowania w awk
Obliczaj sumy, liczności i podsumowania według grup, używając tablic asocjacyjnych indeksowanych wartościami pól.
Agregowanie za pomocą tablic i grupowania w awk to bezpłatna lekcja Linux Command Line & Bash Scripting Mastery na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Linux Command Line & Bash Scripting Mastery, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Linux Command Line & Bash Scripting Mastery zawiera 4 lekcji w sumie.
Czym są tablice asocjacyjne awk
W awk tablica asocjacyjna to struktura przechowująca pary klucz-wartość, w której kluczami mogą być dowolne ciągi znaków lub liczby. W przeciwieństwie do tablic indeksowanych używanych w większości języków, tablice awk są wewnętrznie mapami haszującymi — doskonale nadają się do grupowania i agregowania danych według wartości pól.
- Deklarowanie niejawne: wystarczy przypisać
arr[key] = value - Klucze są domyślnie ciągami znaków (liczby są konwertowane)
- Brak limitu rozmiaru — awk powiększa tablicę w miarę potrzeb
- Idealne do obliczania sum, liczności i podsumowań według grup w jednym przejściu
Nie trzeba inicjalizować klucza przed jego zwiększeniem — awk automatycznie traktuje nieustawiony klucz jako zero lub pusty ciąg znaków.
Zliczanie wierszy w poszczególnych grupach
Najczęściej stosowany wzorzec agregacji polega na zliczaniu, ile razy każda unikatowa wartość pola występuje w danych. Użyj pola $1 (lub dowolnego innego pola) jako klucza tablicy i zwiększaj licznik przy każdym pasującym wierszu.
Blok END jest wykonywany po odczytaniu całego wejścia — to w nim należy wypisać zgromadzone wyniki.
count[$1]++Po przetworzeniu tablica count zawiera całkowitą liczbę wierszy dla każdej unikatowej wartości $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]
}'
Sumowanie pola liczbowego w poszczególnych grupach
Zliczanie to tylko jedna z form agregacji. Aby sumować pole liczbowe pogrupowane według innego pola, dodawaj wartość liczbową do tablicy, której kluczem jest pole grupowania.
Wzorzec wygląda następująco:
- Klucz = pole używane do grupowania (np.
$1jako nazwa użytkownika) - Wartość = bieżąca suma pola liczbowego (np.
$2jako liczba bajtów)
W jednym przejściu awk obliczana jest pełna suma dla każdej grupy — sortowanie ani wstępne przetwarzanie nie są wymagane.
#!/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]
}'
Łączenie zliczania i sumowania w jednym przejściu
awk pozwala jednocześnie utrzymywać wiele tablic, dzięki czemu w jednym przebiegu pliku można obliczyć dla każdej grupy liczność i sumę, a tym samym także średnią. Jest to znacznie wydajniejsze niż dwukrotne uruchamianie potoku.
count[key]++— śledzi liczbę wystąpieńtotal[key] += $N— śledzi bieżącą sumę- W
ENDpodzieltotal[k] / count[k], aby obliczyć średnią dla danej grupy
#!/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]
}'
Klucze wielopolowe do grupowania 2D
Możesz utworzyć klucz złożony, łącząc wiele pól separatorem. Pozwala to przeprowadzić dwuwymiarowe grupowanie bez używania specjalnej składni.
Wybierz separator, który nie może wystąpić w danych (np. SUBSEP, wbudowany separator rekordów awk \034 lub dosłowny znak potoku |).
- Klucz złożony:
arr[$1 SUBSEP $2]lubarr[$1"|"$2] - Rozdzielenie klucza podczas wypisywania:
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]
}
}'
Śledzenie wartości minimalnej i maksymalnej w poszczególnych grupach
Tablice asocjacyjne ułatwiają śledzenie wartości min i max dla poszczególnych grup. Sztuczka polega na inicjalizacji tylko przy pierwszym wystąpieniu każdego klucza za pomocą specjalnego warunku !(key in arr).
!(key in min_arr)ma wartość true przy pierwszym napotkaniu klucza- Po inicjalizacji porównuj wartości i zastępuj je za pomocą standardowego sprawdzenia mniejszości / większości
Ten wzorzec zapobiega pojawieniu się pozornego zera, które zafałszowałoby minimum.
#!/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]
}'
Rozkład częstości — grupy Top-N
Częstym zadaniem w praktyce jest znalezienie Top-N najczęściej występujących wartości. awk zajmuje się zliczaniem, a potoki sort i head służą do uszeregowania i ograniczenia wyników.
Ten wzorzec potoku jest idiomatyczny w pracy z powłoką:
- awk zlicza wystąpienia w tablicy, a w
ENDwypisujecount key sort -rnsortuje liczbowo malejącohead -n 5pozostawia tylko 5 najwyższych wyników
Skupienie awk na agregacji i przekazanie sortowania do sort jest zgodne z filozofią Uniksa.
#!/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
Używanie NR i FNR do agregacji z wielu plików
Podczas przetwarzania wielu plików wbudowane zmienne awk NR (łączna liczba odczytanych rekordów) i FNR (liczba rekordów w bieżącym pliku) pozwalają, za pomocą FILENAME, oznaczyć plik, z którego pochodzi każdy rekord.
FILENAME— nazwa aktualnie odczytywanego plikuFNR == 1— jest spełnione na początku każdego nowego pliku (przydatne do pomijania nagłówków)
Pozwala to przeprowadzać agregację według grup dla poszczególnych plików w całym katalogu dzienników za pomocą jednego wywołania awk.
Wypisywanie posortowanych wyników z tablic awk
Pętla for (key in array) w awk nie gwarantuje kolejności. Aby uzyskać deterministyczne wyniki, przekaż dane wypisywane w bloku END do sort albo zbierz wartości i posortuj je w awk za pomocą funkcji asorti / asort (tylko GNU awk).
Przenośne podejście oparte na potoku powłoki jest zwykle preferowane w skryptach wieloplatformowych:
sort -k1,1— sortowanie alfabetyczne według pierwszego pola (klucza grupy)sort -k2,2rn— sortowanie według drugiego pola (liczności/sumy), liczbowo malejąco
#!/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
Usuwanie kluczy tablicy i czyszczenie stanu
Czasami trzeba zresetować stan agregacji w trakcie przetwarzania — na przykład podczas przetwarzania plików dzienników, w których poszczególne sekcje są oddzielone pustym wierszem lub wartością sygnalizującą.
delete arr[key]— usuwa pojedynczy wpisdelete arr— czyści całą tablicę (GNU awk)- Sprawdzaj istnienie za pomocą
(key in arr)przed uzyskaniem dostępu, aby uniknąć tworzenia pozornych wpisów
Technika ta umożliwia agregację w przesuwanym oknie lub według sekcji bez ponownego uruchamiania 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
}'
Potok z praktyki: podsumowanie dzienników Nginx
Połączmy wszystkie elementy — oto gotowa do użycia produkcyjnie, jednoprzebiegowa agregacja awk dla formatu combined log serwera Nginx. W jednym przebiegu oblicza liczbę żądań, łączną liczbę bajtów i współczynnik błędów dla każdego wirtualnego hosta.
Wykorzystane techniki:
- Klucz złożony:
vhostwyodrębniony z pola - Równoległe tablice:
reqs[],bytes[],errors[] - Warunkowe gromadzenie danych:
$9 >= 400do zliczania tylko odpowiedzi błędnych - Sformatowana tabela
printfw blokuEND
#!/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
}'
Sprawdzenie wiedzy: poprawna inicjalizacja minimum
Sprawdź, czy rozumiesz częsty problem podczas agregacji w awk.
Podsumowanie lekcji: agregacja za pomocą tablic awk
Poznałeś podstawowe wzorce obliczania agregacji według grup w całości za pomocą awk:
- Zliczanie:
count[$key]++— zwiększaj przy każdym wierszu, wypisz wEND - Sumowanie:
total[$key] += $N— gromadź wartości liczbowe dla poszczególnych grup - Średnia: utrzymuj zarówno
count[], jak itotal[], a następnie dziel wEND - Min/Max: zainicjalizuj przy pierwszym wystąpieniu za pomocą
!(key in arr), a następnie porównuj - Klucze złożone: łącz pola separatorem, aby grupować według wielu wymiarów
- Posortowane wyniki: przekaż dane wypisywane przez awk w
ENDdosort, aby uzyskać deterministyczną kolejność - Resetowanie sekcji: użyj
delete arr, aby wyczyścić stan między logicznymi sekcjami wejścia
Wzorce te pozwalają zastąpić rozbudowane zapytania do baz danych lub wielokrotne przejścia potoku jednym wydajnym wywołaniem awk — to niezbędna umiejętność w produkcyjnej pracy z powłoką.
Często zadawane pytania
Czy lekcja „Agregowanie za pomocą tablic i grupowania w awk” jest bezpłatna?
Tak — pełny tekst „Agregowanie za pomocą tablic i grupowania w awk” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Linux Command Line & Bash Scripting Mastery, przejdź na CoddyKit PRO. Kurs Linux Command Line & Bash Scripting Mastery zawiera 4 lekcji w sumie.
Co nauczysz się w „Agregowanie za pomocą tablic i grupowania w awk”?
Obliczaj sumy, liczności i podsumowania według grup, używając tablic asocjacyjnych indeksowanych wartościami pól. Ćwiczysz Linux Command Line & Bash Scripting Mastery z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Linux Command Line & Bash Scripting Mastery?
Nie wymagamy żadnego doświadczenia. Linux Command Line & Bash Scripting Mastery w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Agregowanie za pomocą tablic i grupowania w awk”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Linux Command Line & Bash Scripting Mastery?
Tak. Każda lekcja Linux Command Line & Bash Scripting Mastery zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Rekordy, pola i niestandardowe separatory w awk
- Wzorce, zakresy oraz bloki BEGIN/END
- Agregowanie za pomocą tablic i grupowania w awk
- Funkcje awk, formatowanie printf i generowanie raportów