awk Cheat Sheet
awk '{print $1}' file # first column (whitespace-separated)
awk -F: '{print $1, $7}' /etc/passwd # custom separator
awk '$3 > 100' file # rows where column 3 > 100
awk '/error/ {print $NF}' file # last field of matching lines
awk '{s += $2} END {print s}' file # sum a column
awk 'NR==5, NR==10' file # lines 5 to 10
An awk program is a list of pattern { action } rules run against every input line. If the pattern is missing, the action runs on every line; if the action is missing, the line is printed. awk splits each line into fields $1, $2… on whitespace by default. Always wrap the program in single quotes so the shell does not expand $1.
Which awk you have depends on the distro: Fedora, Arch and openSUSE ship gawk; Debian, Ubuntu and Mint ship mawk unless you install gawk (sudo apt install gawk). Everything in the first sections works in both; gawk-only features are marked.
Printing fields
| Command | What it does |
|---|---|
awk '{print}' f | Print every line (same as cat) |
awk '{print $1, $3}' f | Print columns 1 and 3, separated by a space (OFS) |
awk '{print $1 $3}' f | Print them joined with no separator |
awk '{print $NF}' f | Last field |
awk '{print $(NF-1)}' f | Second-to-last field |
awk '{print NR": "$0}' f | Prefix each line with its line number |
awk '{print NF}' f | Number of fields on each line |
awk '{$2=""; print}' f | Drop column 2 (leaves an extra separator) |
awk '{printf "%-20s %8.2f\n", $1, $2}' f | Formatted output with C-style printf |
awk '{print length($0)}' f | Length of each line |
Separators
| Command | What it does |
|---|---|
awk -F: '...' f | Input field separator is : |
awk -F',' '...' f | Comma-separated (simple CSV without quoted commas) |
awk -F'\t' '...' f | Tab-separated |
awk -F'[:,]' '...' f | Regex separator: colon or comma |
awk -v OFS=',' '{$1=$1; print}' f | Convert whitespace to commas ($1=$1 forces the line to be rebuilt with OFS) |
awk 'BEGIN {FS=":"; OFS="\t"} {print $1,$3}' f | Set separators in a BEGIN block |
awk -v RS='' '{print $1}' f | Paragraph mode: blank lines separate records |
gawk --csv '{print $2}' f.csv | gawk 5.3+: real CSV parsing, handles quoted fields |
Patterns and conditions
| Command | What it does |
|---|---|
awk '/regex/' f | Lines matching a regex (like grep) |
awk '!/regex/' f | Lines not matching |
awk '$1 == "root"' f | Exact field comparison |
awk '$5 ~ /^ERR/' f | Field matches a regex |
awk '$5 !~ /^ERR/' f | Field does not match |
awk '$3 >= 50 && $3 < 100' f | Numeric range with logical AND (|| for OR) |
awk 'NR > 1' f | Skip the header line |
awk 'NF' f | Skip empty lines (NF is 0, which is false) |
awk '/start/,/end/' f | Range from a matching line to the next matching line |
awk 'length > 80' f | Lines longer than 80 characters |
awk '{if ($3 > 0) print "pos"; else print "neg"}' f | if/else inside an action |
Built-in variables
| Command | What it does |
|---|---|
$0 | The whole current record (line) |
$1 ... $NF | Fields of the current record |
NR | Record number across all input |
FNR | Record number within the current file |
NF | Number of fields in the current record |
FS / OFS | Input / output field separator |
RS / ORS | Input / output record separator (default newline) |
FILENAME | Name of the current input file |
ENVIRON["HOME"] | Environment variables |
awk -v lim="$LIMIT" '$2 > lim' f | Pass a shell variable into awk safely |
Arithmetic, arrays and functions
| Command | What it does |
|---|---|
awk '{s+=$1} END {print s}' f | Sum a column |
awk '{s+=$1} END {print s/NR}' f | Average |
awk 'max=="" || $1>max {max=$1} END {print max}' f | Maximum value |
awk '{c[$1]++} END {for (k in c) print c[k], k}' f | Count occurrences of each value (array) |
awk '{s[$1]+=$2} END {for (k in s) print k, s[k]}' f | Sum column 2 grouped by column 1 |
awk '!seen[$0]++' f | Remove duplicate lines, keeping order |
awk '{print toupper($1)}' f | toupper, tolower |
awk '{print substr($1, 1, 3)}' f | Substring: start position (1-based), length |
awk '{gsub(/foo/, "bar"); print}' f | Replace all matches in the line (sub replaces the first) |
awk '{n=split($0, a, ","); print a[n]}' f | Split a string into an array |
awk 'match($0, /[0-9]+/) {print substr($0, RSTART, RLENGTH)}' f | Extract the first number on each line |
gawk '{print strftime("%F %T", $1)}' f | gawk only: format a Unix timestamp |
gawk -i inplace '{gsub(/a/,"b")} 1' f | gawk only: edit a file in place |
Common recipes
Disk usage above 80% from df:
df -h | awk 'NR>1 && $5+0 > 80 {print $6, $5}'
Top 10 client IPs in an nginx or Apache access log:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# or entirely in awk:
awk '{c[$1]++} END {for (ip in c) print c[ip], ip}' access.log | sort -rn | head
Count HTTP status codes (field 9 in the combined log format):
awk '{print $9}' access.log | sort | uniq -c | sort -rn
List human users (UID 1000 and up) with their shells:
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $7}' /etc/passwd
Total memory used by a process name, from ps (RSS in KiB):
ps -eo rss,comm | awk '$2=="firefox" {s+=$1} END {printf "%.1f MiB\n", s/1024}'
Print lines where a column changed compared to the previous line:
awk '$1 != prev {print; prev = $1}' sorted.txt
Join two files on the first column (like a SQL join):
awk 'NR==FNR {name[$1]=$2; next} $1 in name {print $0, name[$1]}' users.txt orders.txt
Swap two columns in a CSV file:
awk -F, -v OFS=, '{t=$1; $1=$2; $2=t; print}' data.csv
Gotchas
- Single quotes, always. In double quotes the shell replaces
$1with its own first argument before awk runs. Pass shell values with-v name="$value". - mawk vs gawk. On Debian and Ubuntu,
awkis mawk:strftimeexists in recent mawk, but-i inplace,--csv,asort,gensubandPROCINFOare gawk-only. Callgawkexplicitly in scripts that rely on them. -F' 'is special. A single space means "runs of whitespace" (the default). For a literal single space use-F'[ ]'.- Strings vs numbers.
$5 > 80on "85%" compares as a string. Add+0($5+0 > 80) to force a numeric comparison. for (k in arr)order is unspecified. Pipe tosort, or in gawk setPROCINFO["sorted_in"]="@ind_str_asc".- Plain
-F,is not a CSV parser. Quoted fields with commas break it. Usegawk --csv(5.3+) or a real CSV tool. - Modifying a field rebuilds the line. After
$3="x",$0is rejoined withOFS, so original spacing is lost.
More text tools: grep cheat sheet, sed cheat sheet, and the bash scripting tutorial for putting them in scripts. Reference: the GNU awk user's guide.
Frequently asked questions
How do I print a specific column with awk?
Use awk '{print $2}' file for the second whitespace-separated column. $0 is the whole line and $NF is the last column.
How do I change the field separator in awk?
Use -F: awk -F: '{print $1}' /etc/passwd. For output, set OFS, for example awk -F: -v OFS=',' '{print $1,$7}'.
How do I sum a column with awk?
awk '{s += $3} END {print s}' file adds up the third column and prints the total after the last line.
Is awk the same as gawk?
awk is the language; gawk (GNU awk) is one implementation. Fedora, Arch and openSUSE use gawk as awk; Debian and Ubuntu install mawk by default, which lacks some gawk extensions. Install the gawk package if you need them.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.