Arrays
This is the chapter where AWK stops feeling like a text filter and starts feeling like a real data-processing tool. AWK arrays are associative — indexed by arbitrary strings, not just sequential numbers — which makes them perfect for exactly the kind of "group by" and "count occurrences of" operations that come up constantly with real-world data.
Associative Arrays — The Basics
No declaration needed — an array springs into existence the first time you assign to any index of it.
fruit["apple"] = 5
fruit["banana"] = 3
print fruit["apple"]
}'
5
Pattern 1 — Counting Occurrences
The single most common array pattern in all of AWK: count how many times each distinct value appears.
$ awk '{ counts[$9]++ } END { for (code in counts) print code, counts[code] }' access.log
200 1543
404 87
500 12
counts[$9]++ works even for a status code that's never been seen before — AWK treats an unset array index as 0 in a numeric context, so the first increment correctly produces 1. No explicit "if this key doesn't exist yet, initialise it" check is needed.
Pattern 2 — Grouping Values
Sometimes the goal isn't a count, but accumulating a running total or list per group — same fundamental pattern, different operation per match.
$ awk '{ totals[$1] += $3 } END { for (cat in totals) printf "%-10s %.2f\n", cat, totals[cat] }' sales.csv
books 245.50
electronics 1830.00
Pattern 3 — Deduplication
Using array keys as a "seen before" check is a clean, idiomatic way to print only unique values, without needing to sort first or compare against previous lines manually.
$ awk '!seen[$1]++' file.txt
This is a famously compact AWK idiom worth understanding fully: seen[$1]++ increments the count for this value and returns its previous value (0 the first time, then 1, 2...). !0 is true, so the first occurrence of any value passes the implicit pattern (and prints, per Chapter 1's "pattern with no action defaults to print"); every subsequent occurrence evaluates !1, !2, etc. — all false, so they're filtered out.
Iterating Over an Array — for...in
for (key in array) visits keys in an implementation-defined order — not insertion order, not alphabetical, not numerical. If a specific output order matters (alphabetical, by count descending), pipe the AWK output into sort afterward rather than trying to control ordering inside AWK itself.
$ awk '{ counts[$9]++ } END { for (c in counts) print counts[c], c }' access.log | sort -rn
Checking Whether a Key Exists — Without Creating It
$ if (arr["maybe"] == "") { ... }
$ # The correct way — (key in array) checks existence without creating it
$ if ("maybe" in arr) { print "exists" }
arr["maybe"] in a condition (rather than using the dedicated in operator) silently creates an empty entry for "maybe" if it didn't already exist — which can quietly inflate a later for...in loop or array length count. Always use (key in array) for a genuine existence check.
Command Reference
| Syntax | What it does |
|---|---|
| arr[key] = value | Assign a value, creating the key if it doesn't exist |
| arr[key]++ | Increment a counter, treating a missing key as 0 |
| for (key in arr) | Iterate over all keys, in unspecified order |
| (key in arr) | Check existence WITHOUT creating the key as a side effect |
| delete arr[key] | Remove a specific key from the array |
Chapter 6 Quick Reference
- Associative arrays — indexed by arbitrary strings, created on first assignment, no declaration needed
- Counting: counts[key]++ — missing keys treated as 0 automatically
- Grouping/totals: totals[key] += value, read in END
- Deduplication: !seen[$1]++ — a compact, genuinely useful idiom once understood
- for (key in arr) — order is NOT guaranteed; pipe to sort if order matters
- (key in arr) — checks existence WITHOUT creating the key; referencing arr[key] directly DOES create it
- Next chapter: control flow — if/else, for and while loops in AWK