Fields
This chapter is the real foundation of why AWK exists at all — automatic field splitting. Every line AWK reads (a "record") gets split into pieces (its "fields") without you writing any splitting logic yourself. Understanding exactly how that splitting works, and how to control it, unlocks almost everything else in this course.
Fields — $0, $1, $2...
By default, AWK splits each line on whitespace (spaces and/or tabs, any amount) into numbered fields, accessible as $1, $2, and so on. $0 is special — it always refers to the entire current line, unsplit.
$0 = the whole line: "philip admin active 42"
$ echo "philip admin active 42" | awk '{ print $1 }'
philip
$ echo "philip admin active 42" | awk '{ print $2, $4 }'
admin 42
$ # A field beyond the actual number of fields is just empty, not an error
$ echo "a b" | awk '{ print $5 }'
(empty line)
The Built-In Variables That Describe the Current Line
$NF conveniently refers to the last field, whatever its number happens to be.$ awk '{ print NF }' file.txt
$ # $NF — print the LAST field of each line, regardless of how many there are
$ awk '{ print $NF }' file.txt
$ # NR — number every line, like cat -n
$ awk '{ print NR, $0 }' file.txt
$ # Only print line 5 specifically
$ awk 'NR==5' file.txt
$NF handles that without needing to know NF's actual value in advance.
Field Separators — FS and OFS
Default whitespace splitting works for a lot of text, but plenty of real data is comma-separated, colon-separated, or otherwise structured differently. FS (Field Separator) controls how AWK splits the input; OFS (Output Field Separator) controls what gets placed between fields when printing them back out together.
$ awk -F',' '{ print $2 }' data.csv
$ # Colon-separated — classic /etc/passwd format
$ awk -F':' '{ print $1, $3 }' /etc/passwd
$ # Changing OFS affects how fields are joined when you print several together
$ awk -F',' 'BEGIN{OFS="|"} { print $1, $2 }' data.csv
name|value
print $1, $2 (comma-separated print arguments) or by reassigning any field (which forces AWK to rebuild $0 using OFS). Printing $0 directly without modifying any field still shows the original separators untouched.
BEGIN and END blocks — running code outside the per-line loop
Setting OFS above used a BEGIN block — code that runs once, before any input is read, rather than once per line. There's a matching END block that runs once after all input has been processed. Both get full coverage in Chapter 3, but they're worth introducing here since FS/OFS setup is one of their most common uses.
Command Reference
| Reference | What it gives you |
|---|---|
| $0 | The entire current line, unsplit |
| $1, $2, ... | Individual fields, numbered from 1 |
| $NF | The last field, regardless of how many fields exist |
| NF | The number of fields in the current line |
| NR | The current line number, across all input |
| FNR | The current line number, reset per file |
| -F',' | Sets the input field separator from the command line |
| BEGIN{FS=","; OFS="|"} | Sets separators inside the program itself |
Chapter 2 Quick Reference
- $0 — the whole line; $1, $2... — individual fields, split by whitespace by default
- $NF — always the last field, whatever NF happens to be that line
- NF — field count; NR — running line count across all input; FNR — line count, resets per file
- FS — controls input splitting (set via -F or BEGIN); OFS — controls output joining
- OFS only applies when fields are actually rejoined — printing $0 unmodified shows the original text untouched
- Next chapter: patterns and conditions — regex patterns, ranges, and the BEGIN/END blocks introduced here in full