On this page
- What AWK is
- Which awk do you have?
- Create two sample files
- Fields and records: the five things to remember
- Print a column
- Filter rows
- Do math
- BEGIN and END
- Format the output with printf
- Count things with an array
- Use a variable from the shell
- Put the program in a file
- Five beginner mistakes (all tested)
- 1. Using double quotes around the program
- 2. Comparing numbers when the header is in the way
- 3. Comma or no comma in print
- 4. Forgetting that new variables start empty
- 5. Expecting array loops to come out in order
- AWK, grep, sed or cut?
- Frequently asked questions
- What does AWK stand for?
- Is awk the same as gawk?
- Can AWK edit a file in place?
- Is AWK still worth learning?
- Further reading
You have a log file, a CSV export or the output of some command, and you want one column, or only the rows that match a condition, or a total. You could open a spreadsheet or write a Python script. Or you could type one line of AWK and be done. AWK reads text line by line, splits each line into fields, and lets you act on them. This guide takes you from zero to useful, with sample files you can copy and run, and the exact output you should see.
What AWK is
AWK is a small programming language built for processing text that is organised in lines and columns. The name comes from the initials of its three original authors: Aho, Weinberger and Kernighan. Most Linux systems ship with some version of it, so you can usually start right away.
The idea is simple. AWK reads your input one line (called a record) at a time. It splits each line into fields, and for every line it checks your rules. Each rule is a pattern plus an action in curly braces:
awk 'pattern { action }' fileIf the pattern matches the current line, the action runs. Leave out the pattern and the action runs on every line. Leave out the action and AWK prints the matching lines.
Which awk do you have?
"awk" is a name shared by several programs. The most common are gawk (GNU awk), mawk (the default on some Debian-family systems) and the BWK awk that macOS uses. Check yours:
awk --version # works on gawk (and on the newer mawk I tested)
awk -W version # worked on both gawk 5.2.1 and mawk 1.3.4Everything in this guide runs the same on gawk 5.2.1 and mawk 1.3.4, which are the two I tested. Where a feature works in only one of them, the article says so. I did not test macOS awk.
Create two sample files
Paste this into a terminal. Every example below uses these files.
cat > sales.csv <<'EOF'
date,region,product,qty,price
2026-10-01,north,pen,10,1.50
2026-10-01,south,book,3,12.00
2026-10-02,north,book,2,12.00
2026-10-02,east,pen,25,1.50
2026-10-03,south,pen,5,1.50
EOF
cat > access.log <<'EOF'
10.0.0.1 - - [24/Oct/2026:10:00:01 +0000] "GET /index.php HTTP/1.1" 200 512
10.0.0.2 - - [24/Oct/2026:10:00:02 +0000] "GET /about HTTP/1.1" 404 128
10.0.0.1 - - [24/Oct/2026:10:00:03 +0000] "POST /login HTTP/1.1" 302 0
10.0.0.3 - - [24/Oct/2026:10:00:04 +0000] "GET /index.php HTTP/1.1" 200 512
10.0.0.2 - - [24/Oct/2026:10:00:05 +0000] "GET /missing HTTP/1.1" 404 128
10.0.0.1 - - [24/Oct/2026:10:00:06 +0000] "GET /index.php HTTP/1.1" 500 64
EOFFields and records: the five things to remember
| You write | It means |
|---|---|
$0 | The whole current line |
$1, $2, ... | The first field, the second field, and so on |
NF | The number of fields on the current line |
$NF | The last field ($(NF-1) is the one before it) |
NR | The current line number |
By default, AWK splits on runs of spaces and tabs. For a comma-separated file, tell it the separator with -F.
Print a column
awk -F, '{print $2}' sales.csvregion
north
south
north
east
southThe first line is the header. Skip it by only acting when the line number is greater than 1, and print two columns by separating them with a comma:
awk -F, 'NR>1 {print $3, $4}' sales.csvpen 10
book 3
book 2
pen 25
pen 5Filter rows
A pattern on its own prints every line that matches. Match a field exactly:
awk -F, '$2 == "north"' sales.csv2026-10-01,north,pen,10,1.50
2026-10-02,north,book,2,12.00Or match text anywhere in the line with a regular expression between slashes:
awk '/404/' access.log10.0.0.2 - - [24/Oct/2026:10:00:02 +0000] "GET /about HTTP/1.1" 404 128
10.0.0.2 - - [24/Oct/2026:10:00:05 +0000] "GET /missing HTTP/1.1" 404 128Combine a condition with an action. In the log, the status code is field 9 and the requested path is field 7:
awk '$9 == 404 {print $7}' access.log/about
/missingDo math
AWK treats numeric-looking fields as numbers, so you can add and multiply right away. Total revenue is quantity times price, added up over every row except the header:
awk -F, 'NR>1 {total += $4 * $5} END {print "Total:", total}' sales.csvTotal: 120Two things happened there. total was never declared; AWK created it and started it at zero. And the END block ran once, after the last line, which is the right place for final results.
BEGIN and END
BEGIN { ... }runs once before any input is read. Use it to print a heading or set variables. It works even with no input file:awk 'BEGIN {print "Hello, AWK"}'printsHello, AWK.END { ... }runs once after the last line. Use it for totals. Inside it,NRholds the total number of lines, soawk 'END {print NR}' access.logprints6.
Format the output with printf
printf works like the C function: you give a format string and the values. It does not add a newline for you, so end the format with \n.
awk -F, 'NR>1 {printf "%-6s %-5s %6.2f\n", $2, $3, $4*$5}' sales.csvnorth pen 15.00
south book 36.00
north book 24.00
east pen 37.50
south pen 7.50%-6s is a left-aligned string in 6 characters, and %6.2f is a number with two decimals in 6 characters.
Count things with an array
AWK arrays are indexed by text, which makes "count by group" short to write. This counts rows per region:
awk -F, 'NR>1 {n[$2]++} END {for (k in n) print k, n[k]}' sales.csv | sorteast 1
north 2
south 2Note the | sort at the end. It is there on purpose, and the mistakes section below explains why.
Use a variable from the shell
Pass values in with -v instead of pasting them into the program:
awk -F, -v region=north '$2 == region' sales.csvThis prints the same two north rows as before, but now the region can come from a shell variable.
Put the program in a file
When a one-liner gets long, save it and run it with -f:
# report.awk
BEGIN { FS = ","; print "Sales report" }
NR > 1 { total += $4 * $5; n++ }
END { printf "%d orders, total %.2f\n", n, total }awk -f report.awk sales.csvSales report
5 orders, total 120.00Five beginner mistakes (all tested)
1. Using double quotes around the program
The shell replaces $1 inside double quotes before AWK ever sees it. The variable is empty, so AWK receives {print } and prints whole lines:
awk "{print $1}" access.log # wrong: prints the entire line
awk '{print $1}' access.log # right: prints the first fieldWrap AWK programs in single quotes.
2. Comparing numbers when the header is in the way
You want rows with quantity over 5. This looks right:
awk -F, '$4 > 5 {print $3, $4}' sales.csvproduct qty
pen 10
pen 25The header sneaked in. In the header row, field 4 is the text qty, so AWK compares it with 5 as text, and it counts as "greater". Add NR>1 && to skip the header, and you get only pen 10 and pen 25.
3. Comma or no comma in print
A comma puts a space between the values; no comma glues them together:
echo 'a b' | awk '{print $1,$2; print $1 $2}'
# a b
# ab4. Forgetting that new variables start empty
An unset variable is both zero and an empty string, depending on how you use it. That is why total += ... works without setup:
awk 'BEGIN {print x+0, "[" x "]"}'
# 0 []5. Expecting array loops to come out in order
for (k in n) visits keys in no guaranteed order. When I ran the region count without sort, gawk and mawk printed the same counts in a different order. Pipe the output through sort when order matters.
AWK, grep, sed or cut?
- grep finds lines that match.
- sed edits text, mostly search and replace.
- cut slices fixed columns.
- AWK is the one to reach for when you need columns and a condition or some arithmetic.
For a quick "show me lines containing X", grep is shorter. Once you need a column, a comparison or a total, AWK pays off.
Frequently asked questions
What does AWK stand for?
The initials of its creators: Alfred Aho, Peter Weinberger and Brian Kernighan.
Is awk the same as gawk?
Not always. awk is a name that points to whichever version your system chose, and on many Linux systems it is gawk. The basics in this guide work in both gawk and mawk, but gawk adds extra features such as asort() and gensub() that mawk does not have. In my test, calling those in mawk failed with "function never defined".
Can AWK edit a file in place?
Plain AWK prints to the screen; it does not change the input file. gawk can do it with -i inplace (I tested this on gawk 5.2.1). For a method that works with any awk, write to a temporary file and then move it over the original.
Is AWK still worth learning?
For fast work on logs, CSV files and command output, yes. A few lines of AWK often replace a throwaway script. For larger programs with complex data, a general-purpose language is the better tool.
Further reading
Free resources for this topic
Code snippets and fixes for this topic
Get one practical tip every week
New tutorials, fixes and free cheat sheets from DEV Talk, straight to your inbox. No spam, unsubscribe in one click.
Have a question about this post?
Ask the community: other developers and the author can answer.
Get notified about new articles
One click, no email needed. Turn it off anytime with the bell at the top.
Get new articles on your iPhone
Add DEV Talk to your Home Screen, open it, then tap the bell.
Enjoying the content?
If this article helped you, you can support the author with a coffee. It keeps new posts coming.
Comments 0
No comments yet
Be the first to share your thoughts.