The awk command in Linux

awk is a small programming language for columnar text. It splits each line into fields ($1, $2, …, whole line $0) and runs your program on every line — which makes "give me column 2 of this output" a five-character program: {print $2}. Add patterns, conditions and arithmetic and it replaces many small scripts.

How awk works

awk's worldview: input is a sequence of records (lines, by default) which split into fields on a separator (whitespace, by default — collapsing runs of it, which is why awk handles aligned command output that defeats cut). A program is a list of pattern-action pairs; for each record, every pattern is tested and its action runs on match. A missing pattern matches everything; a missing action prints the record. BEGIN and END are patterns for before-any-input and after-all-input — the natural home of headers and totals.

What lifts awk from extractor to language is its data structure: associative arrays, indexed by arbitrary strings, created on first touch. count[$1]++ builds a frequency table of a column in four characters; !seen[$0]++ de-duplicates while preserving order. Variables need no declaration and convert between string and number by context. Half the "impossible one-liners" you will meet are just an associative array and the record-field model doing what they were built for.

Syntax

awk [-F SEP] 'PROGRAM' [FILE...]

Common options

OptionWhat it does
'{print $1}'Print the first field of every line.
-F","Set the field separator (default is any whitespace).
'/pat/ {…}'Run the action only on lines matching a pattern.
'$3 > 100'Conditions on fields select lines (default action: print).
NR / NFBuilt-ins: current line number / number of fields.
END {…}Run after all input — where totals get printed.

How to use awk: examples

$ ps aux | awk '{print $2, $11}'

Just the PID and command columns from ps.

$ awk -F',' '{print $3}' data.csv

Third column of a CSV (for real-world CSVs with quoted commas, use a proper parser).

$ df -h | awk '$5+0 > 80 {print $6, $5}'

Mount points over 80% full — the +0 coerces "85%" to a number.

$ awk '{sum += $1} END {print sum}' numbers.txt

Sum a column. The moment awk starts replacing spreadsheets.

$ awk 'NR % 2 == 1' file.txt

Every odd-numbered line.

$ awk -F: '{print $1}' /etc/passwd | sort

All user names on the system: /etc/passwd is colon-separated, field 1 is the name.

Real-world use cases for awk

Instant log analytics

Which endpoints are slow? awk '$10 > 1000 {print $7}' access.log | sort | uniq -c | sort -nr — filter requests over 1000 ms, extract the URL field, count by frequency. Four piped commands doing what would otherwise mean importing gigabytes into a database.

Ad-hoc reports from CSV exports

Finance sends a CSV; you need the total of column 4 for rows marked "paid": awk -F, '$2=="paid" {s+=$4} END {printf "%.2f\n", s}' export.csv. No spreadsheet opened, answer in one line, trivially re-runnable next month.

Pro tips and common mistakes

Frequently asked questions about awk

When should I use awk instead of cut?

cut is fine for fixed single-character delimiters. awk wins whenever fields are separated by variable whitespace (like most command output), or when you need conditions, arithmetic or reordering.

How do I print the last field?

awk '{print $NF}' — NF holds the number of fields, so $NF is the last one and $(NF-1) the one before it.

Why doesn't $1 mean the same as in bash?

Inside single quotes the shell leaves $1 alone and awk interprets it as field one. That is exactly why awk programs are wrapped in single quotes — double quotes would let the shell eat the dollar signs.

Related commands

grep

Find lines matching a pattern in files or piped input — the workhorse of text search.

sed

Stream-edit text: substitute, delete lines, and edit files in place with -i.

cut

Slice fields or character ranges out of each line — quick column extraction for delimited data.

Want to build real fluency? The interactive course takes you through awk and every other essential command with guided, checked exercises.