Print Columns
Fields split on whitespace by default. is the first field, the last, the whole line.
| Command | What it does |
|---|---|
| First column of every line | |
| Two columns, separated by a space | |
| Last column | |
| Second-to-last column | |
| Mix fields with literal text | |
| PID and command from ps | |
| Size and name from ls | |
| Number every line |
Column Ranges
Printing everything except one column is the awkward case, because awk has no slice syntax.
| Command | What it does |
|---|---|
| A fixed range of columns | |
| All but the first field (leaves a leading space) | |
| All but the first field, leading space trimmed | |
| All but the last field | |
| Drop the last field (gawk and mawk) | |
| Field 3 to end of line, original spacing kept |
Assigning to a field rebuilds with , so flattens any column padding the file had. The / form avoids that, at the cost of matching the wrong spot if that text also appears earlier in the line. For an arbitrary start column, loop:
awk '{for (i = 3; i <= NF; i++) printf "%s%s", $i, (i < NF ? OFS : ORS)}' fileField Separators
sets the input separator; is what goes between fields on output.
| Command | What it does |
|---|---|
| Comma-separated input | |
| Tab-separated input | |
| Every username on the system | |
| The separator can be a regex: comma or semicolon | |
| Comma with optional spaces around it | |
| Same as -F, set inside the program | |
| Convert CSV to TSV ( forces the rebuild) | |
| Custom output separator |
NR and NF
is the current line number, the number of fields on the line. Both double as filters.
| Command | What it does |
|---|---|
| Print line 5 only | |
| Skip the header line | |
| A line range | |
| Every second line | |
| Count lines, like wc -l | |
| How many fields each line has | |
| Drop blank lines (0 fields is false) | |
| Only lines with exactly 7 fields (catch bad CSV rows) | |
| FNR resets per file; print each file's name once |
Patterns and Conditions
The shape is : the action runs on lines where the pattern holds. Either half can be omitted.
| Command | What it does |
|---|---|
| Lines matching a regex (like grep) | |
| Column 2 of matching lines | |
| Lines NOT matching | |
| Exact string match on a field | |
| Numeric comparison on a field | |
| Regex match on one field only | |
| Field does not match | |
| Combine with && and || | |
| Range: from one match to the next | |
| Disk usage percent per mount |
if/else lives inside the action:
awk '{if ($3 > 100) print $1 " high"; else print $1 " ok"}' data.txt
awk '{print $1, ($3 > 100 ? "high" : "ok")}' data.txtLoops and Control Flow
| Command | What it does |
|---|---|
| One field per line | |
| Loop with no input at all | |
| Same loop, while form | |
| Skip a line and read the next one | |
| Stop at the first hit (fast on huge files) | |
| Bail out early instead of reading the rest | |
| Set the shell exit status from awk |
skips the remaining rules for that line; jumps straight to , so an block still runs after it.
BEGIN and END
runs before the first line, after the last: headers, totals, averages.
| Command | What it does |
|---|---|
| Sum a column (the classic) | |
| Average of a column | |
| Maximum of a column | |
| Count matches ( prints 0 instead of blank) | |
| Add a header line | |
| BEGIN is where FS/OFS setup goes |
printf
formats output with C-style specifiers and adds no newline unless you write .
| Command | What it does |
|---|---|
| String, one per line | |
| Left-pad to 15, right-pad to 8: aligned columns | |
| Two decimal places | |
| Integer plus a literal percent sign | |
| Mix strings and numbers | |
| Decimal to hex ( for octal) | |
| Big numbers without scientific notation | |
| Works in END too |
on a number over about 16 digits falls back to and prints ; or keeps the digits.
Quoting and Output
| Command | What it does |
|---|---|
| Everything on one line, no newline per record | |
| Wrap a field in double quotes | |
| Same thing without escaping | |
| Put a literal tab between fields | |
| Strip Windows carriage returns | |
| Write to a file from inside awk | |
| Append instead of overwriting | |
| Split input into one file per column-1 value |
inside the program is awk's redirect, not the shell's, so it needs no quoting beyond the single quotes already around the program. awk keeps every file it writes open, so splitting into thousands of files needs .
Arrays and Counting
awk arrays are string-keyed maps, which makes counting and grouping one-liners.
| Command | What it does |
|---|---|
| Count occurrences of each value in column 1 | |
| Remove duplicate lines, order preserved (uniq without sort) | |
| First line per distinct column-1 value | |
| Sum column 2 per key in column 1 | |
| Keys that appear more than once |
The count-and-sort pipeline for "top talkers" in a log (see the grep cheat sheet for the pure-grep half):
awk '{print $1}' access.log | sort | uniq -c | sort -rn | headString Functions
| Command | What it does |
|---|---|
| Line length in characters | |
| Lines longer than 80 characters | |
| First 3 characters of field 1 | |
| Change case | |
| Position of a substring (0 if absent) | |
| Split a field on and use a piece | |
| Replace first match: trim leading spaces | |
| Replace all matches, here only in field 3 | |
| Print only the matched text, like grep -o | |
| Format into a string |
and modify in place and return the replacement count. For pure stream find-and-replace, sed is usually the shorter tool.
Variables
| Command | What it does |
|---|---|
| Pass a value in with -v | |
| Pass a shell variable in safely | |
| Match against a variable (in a script) | |
| Read environment variables directly | |
| Output record separator: join lines with commas | |
| Paragraph mode: records split on blank lines |
Shell Commands from awk
awk can shell out mid-program, which covers the jobs a pipeline alone cannot.
| Command | What it does |
|---|---|
| Run a shell command once per line | |
| Capture a command's output into a variable | |
| Pipe awk's own output into a command | |
| Read a command's output line by line | |
| Find PIDs and kill them |
A command stays open after the first read, so running it again in the same program returns nothing until you .
Scripts and Recipes
Past one line, put the program in a file and run it with , or give it a shebang.
awk -f report.awk access.log#!/usr/bin/awk -f
BEGIN { FS = ","; print "user,total" }
NR > 1 { total[$1] += $3 }
END { for (u in total) print u "," total[u] }Everyday pipelines:
| Command | What it does |
|---|---|
| Processes over 50% CPU | |
| Mounts over 80% full ( strips the %) | |
| Memory in use | |
| Listening addresses and ports | |
| Human (non-system) users |
Gotchas
- Single-quote the program. In double quotes the shell expands before awk runs, which silently breaks the script.
- means no awk is installed, which happens on slim containers: or . A almost always means the shell ate part of the program, so check the quoting before the logic.
- Not all awks are equal: Linux usually has gawk or mawk, macOS ships an older BSD awk. , , and -style classes are gawk extras; everything on this sheet sticks to the portable core.
- Comparisons are type-sensitive: compares numbers, but if the field has stray characters awk may compare strings. Force a number with .
- Assigning to any field (even ) rebuilds with OFS, which rewrites the separators on output. Sometimes that is exactly what you want; sometimes it is the bug.
- Uninitialized variables are and 0 at the same time, so needs no setup, and a missing field prints as empty rather than erroring.
- grep selects lines and sed rewrites them; see the grep cheat sheet and sed cheat sheet for the other two thirds of the toolkit.