Skip to content
Laviyx Learn

Try

Linux and Bash course menu

Linux awk Tutorial: Columns, Filters and Totals

Learn awk with examples: print columns, set field separators, filter rows, calculate totals and averages, group with associative arrays, and format reports with printf.

Intermediate5 min readUpdated
On this page

awk is a small language for data in columns. It reads a file line by line, splits each line into fields, and runs your program on them.

By default, awk splits on spaces. $1 is the first field, $2 the second, $NF the last, and $0 the whole line:

Terminal
echo "Asha 30 Hyderabad" | awk '{print $1, $3}'
ls -l /etc/hostname | awk '{print $1, $NF}'
Output
Asha Hyderabad
-rw-r--r-- /etc/hostname

Set the separator with -F:

Terminal
awk -F, '{print $1, $4}' staff.csv | head -n 3
Output
name salary
Asha 90000
Ravi 55000

Filter rows#

A condition before the braces selects lines. NR is the line number, so NR > 1 skips the header:

Terminal
awk -F, 'NR > 1 && $4 > 80000 {print $1, $4}' staff.csv
Output
Asha 90000
Meena 105000
Divya 88000

With no action, awk prints the matching line:

Terminal
awk -F, '$2 == "Pune"' staff.csv
awk -F, '/Support/' staff.csv
Output
Ravi,Pune,Sales,55000
Divya,Pune,Engineering,88000
Karan,Chennai,Support,42000

Totals and averages#

Variables start at zero. END runs after the last line:

Terminal
awk -F, 'NR > 1 {sum += $4; n++} END {print "Total:", sum; print "Average:", sum / n}' staff.csv
Output
Total: 441000
Average: 73500

Group by a column#

Arrays can use text as keys, which makes grouping easy:

Terminal
awk -F, 'NR > 1 {total[$3] += $4} END {for (d in total) print d, total[d]}' staff.csv | sort
Output
Engineering 283000
Sales 116000
Support 42000

This is like SELECT department, SUM(salary) ... GROUP BY department in SQL.

Count things#

Terminal
awk -F, 'NR > 1 {count[$2]++} END {for (c in count) print count[c], c}' staff.csv | sort -nr
Output
3 Hyderabad
2 Pune
1 Chennai

Formatted output#

printf controls the layout. %-12s is left-aligned text, 12 characters wide, and %8d is a number 8 characters wide:

Terminal
awk -F, 'NR > 1 {printf "%-8s %8d\n", $1, $4}' staff.csv
Output
Asha        90000
Ravi        55000
Meena      105000
Karan       42000
Divya       88000
Arjun       61000

Built-in variables#

VariableMeaning
NRCurrent line number
NFNumber of fields on this line
FSInput field separator
OFSOutput field separator
$0The whole line

BEGIN runs before the first line, and OFS joins output fields:

Terminal
awk 'BEGIN {FS=","; OFS=" | "} NR <= 2 {print $1, $2}' staff.csv
Output
name | city
Asha | Hyderabad

Passing shell variables#

Use -v, and do not paste variables into the program:

Terminal
limit=100000
awk -F, -v limit="$limit" 'NR > 1 && $4 >= limit {print $1}' staff.csv
Output
Meena

When to use which tool#

TaskTool
Find linesgrep
Replace textsed
Work with columns or totalsawk
Anything biggerPython

Common mistakes#

Practice#

Practice exercise

Print the highest salary in each city, sorted by city.

Show hint

Use an array indexed by city, and update it when $4 is bigger: if ($4 > max[$2]) max[$2] = $4.

Show solution
Terminal
awk -F, 'NR > 1 {if ($4 > max[$2]) max[$2] = $4} END {for (c in max) print c, max[c]}' staff.csv | sort
Output
Chennai 42000
Hyderabad 105000
Pune 88000

Key takeaway#

Next: File Permissions.

Finished this lesson?