awk
awk is a line-oriented text-processing language: it reads input record by record
(usually line by line), splits each record into fields, and runs pattern-action
rules against it. Its power comes from a compact set of built-in variables like
NR, NF and FS, a library of string and numeric functions, and the special
BEGIN/END patterns. This page is a searchable, offline reference to all of
them, each with a working snippet.
How it works
An awk program is a sequence of pattern { action } rules. For every input
record:
- The record is split into fields
$1,$2, … up to$NFusing the field separatorFS;$0is the whole record. - Each rule whose pattern matches runs its action. A pattern can be a regex
/error/, a boolean expressionNR > 1, a range/START/,/END/, or the specialBEGIN/ENDmarkers. - Built-in variables track state:
NR(record number),NF(field count),FNR(per-file record number),FILENAME, and the separatorsFS,OFS,RS,ORS.
String functions such as split, gsub, sub, substr, match, index and
sprintf let you reshape text, while int, sqrt, log and friends handle
numbers. print and printf produce output, and getline reads extra input.
Practical examples
Sum a column and print the total at the end:
awk '{ sum += $2 } END { print "total:", sum }' data.tsv
Print the last field of each line regardless of how many fields there are:
awk '{ print $NF }' file
Reformat a colon-delimited file into tab-separated output:
awk 'BEGIN { FS=":"; OFS="\t" } { print $1, $3 }' /etc/passwd
Skip the header row and process from line 2 onward:
awk 'NR > 1 { print $0 }' report.csv
Print only lines where a field matches a value:
awk -F',' '$3 == "ERROR" { print $0 }' logs.csv
Replace every occurrence of a pattern in a field (not the whole line):
awk '{ gsub(/foo/, "bar", $2); print }' file
Key built-in variables at a glance
| Variable | Meaning |
|---|---|
$0 | The entire current record |
$1, $2, … | Fields 1, 2, … (1-indexed) |
$NF | The last field |
NR | Total record number across all files |
FNR | Record number within the current file (resets per file) |
NF | Number of fields in the current record |
FS | Input field separator (default: whitespace) |
OFS | Output field separator (default: space) |
RS | Input record separator (default: newline) |
ORS | Output record separator (default: newline) |
FILENAME | Name of the current input file |
Things that trip people up
- awk indexes from 1, not 0.
$1is the first field;substr(s,1,3)returns the first three characters. - Unset variables are 0 in numeric context and "" in string context — not errors.
- Assigning to a field (e.g.
$2 = "new") rebuilds$0usingOFSas the separator, which is how you do in-place column edits. NRkeeps counting across multiple input files; useFNRwhen you need per-file line numbers.subreplaces only the first match;gsubreplaces all matches. Both modify the target in place and return the match count.