DEV Community

Cover image for AWK Command in Linux: Beginner’s Guide with Examples
devTalk
devTalk

Posted on Originally published at dev-talk.com

AWK Command in Linux: Beginner’s Guide with Examples

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 }' file
Enter fullscreen mode Exit fullscreen mode

If 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.4
Enter fullscreen mode Exit fullscreen mode

Everything 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
EOF
Enter fullscreen mode Exit fullscreen mode

Fields 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.csv
Enter fullscreen mode Exit fullscreen mode
region
north
south
north
east
south
Enter fullscreen mode Exit fullscreen mode

The 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.csv
Enter fullscreen mode Exit fullscreen mode
pen 10
book 3
book 2
pen 25
pen 5
Enter fullscreen mode Exit fullscreen mode

Filter rows

A pattern on its own prints every line that matches. Match a field exactly:

awk -F, '$2 == "north"' sales.csv
Enter fullscreen mode Exit fullscreen mode
2026-10-01,north,pen,10,1.50
2026-10-02,north,book,2,12.00
Enter fullscreen mode Exit fullscreen mode

Or match text anywhere in the line with a regular expression between slashes:

awk '/404/' access.log
Enter fullscreen mode Exit fullscreen mode
10.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 128
Enter fullscreen mode Exit fullscreen mode

Combine 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
Enter fullscreen mode Exit fullscreen mode
/about
/missing
Enter fullscreen mode Exit fullscreen mode

Do 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.csv
Enter fullscreen mode Exit fullscreen mode
Total: 120
Enter fullscreen mode Exit fullscreen mode

Two 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"}' prints Hello, AWK.
  • END { ... } runs once after the last line. Use it for totals. Inside it, NR holds the total number of lines, so awk 'END {print NR}' access.log prints 6.

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.csv
Enter fullscreen mode Exit fullscreen mode
north  pen    15.00
south  book   36.00
north  book   24.00
east   pen    37.50
south  pen     7.50
Enter fullscreen mode Exit fullscreen mode

%-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 | sort
Enter fullscreen mode Exit fullscreen mode
east 1
north 2
south 2
Enter fullscreen mode Exit fullscreen mode

Note 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.csv
Enter fullscreen mode Exit fullscreen mode

This 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 }
Enter fullscreen mode Exit fullscreen mode
awk -f report.awk sales.csv
Enter fullscreen mode Exit fullscreen mode
Sales report
5 orders, total 120.00
Enter fullscreen mode Exit fullscreen mode

Five 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 field
Enter fullscreen mode Exit fullscreen mode

Wrap 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.csv
Enter fullscreen mode Exit fullscreen mode
product qty
pen 10
pen 25
Enter fullscreen mode Exit fullscreen mode

The 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
# ab
Enter fullscreen mode Exit fullscreen mode

4. 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 []
Enter fullscreen mode Exit fullscreen mode

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


Originally published on DEV Talk.

Top comments (0)