AWK fits naturally after grep and sed. Grep finds matching lines, sed edits streams, and AWK lets you work with columns, conditions, totals, and reports without opening a spreadsheet or writing a full script.
AWK = Pattern scanning and text processing language.
Full Form: Named after creators Aho, Weinberger, and Kernighan (1977, Bell Labs).
One-liner definition:
AWK reads files line-by-line, splits each line into fields, and lets you process/filter/transform data using patterns and actions.
| Reason | Explanation |
|---|---|
| Text processing | Parse logs, configs, and CSV files quickly |
| Data extraction | Pull specific columns without loading into Excel |
| Quick calculations | Sum, average, and count without writing a separate script |
| One-liners | Handle small reporting tasks without opening a larger scripting workflow |
| Universally available | Pre-installed on Linux, macOS, WSL |
/etc/passwd)| Role | Use Case |
|---|---|
| SysAdmins | Parse logs, monitor systems |
| DevOps | Process CI/CD outputs, configs |
| Security Analysts | Analyze access logs, extract IPs |
| Pentesters | Recon data parsing, wordlist manipulation |
| Data Engineers | Quick ETL, data cleaning |
| Developers | Debug logs, test output parsing |
| Tool | Best For |
|---|---|
| grep | Finding/matching patterns |
| sed | Find and replace, line editing |
| awk | Column-based processing, calculations |
| cut | Simple column extraction (less powerful) |
Search -> grep | Replace -> sed | Columns + Math -> awk
awk [OPTIONS] 'PATTERN {ACTION}' filename
| Component | Meaning |
|---|---|
| OPTIONS | Flags like -F for delimiter |
| PATTERN | Condition to match (optional) |
| ACTION | What to do with matched lines |
| filename | Input file |
If no PATTERN: Action runs on every line.
If no ACTION: Prints entire matching line.
| Option | Meaning | Example |
|---|---|---|
| -F | Field separator | -F, for CSV, -F: for /etc/passwd |
| -v | Define variable | -v threshold=50000 |
| -f | Read awk script from file | awk -f script. awk data.txt |
Default separator: Whitespace (space/tab).
# CSV (comma)
awk -F, '{print $1}' file.csv
# TSV (tab)
awk -F'\t' '{print $1}' file. tsv
# Colon (like /etc/passwd)
awk -F: '{print $1}' /etc/passwd
# Pipe
awk -F'|' '{print $1}' file. psv
# Multiple separators (comma OR semicolon)
awk -F'[,;]' '{print $1}' file.txt
| Variable | Meaning | Example Value |
|---|---|---|
| $0 | Entire current line | 101,john,engineering,75000,newyork,active |
| $1, $2... | 1st, 2nd... field | $1=101, $2=john |
| NR | Number of Record (line number) | 1, 2, 3... |
| NF | Number of Fields in current line | 6 (for 6-column CSV) |
| FS | Field Separator (input) | , |
| OFS | Output Field Separator | Default: space |
| RS | Record Separator | Default: newline |
| ORS | Output Record Separator | Default: newline |
| FILENAME | Current filename | emp.csv |
Runs before processing any lines.
awk 'BEGIN {print "Starting..."} {print $0}' file.txt
Use cases: Print headers, initialize variables, set FS.
awk 'BEGIN {FS=","; print "Name,Salary"} NR>1 {print $2,$4}' emp.csv
Runs after all lines processed.
awk '{sum+=$1} END {print "Total:", sum}' numbers.txt
Use cases: Print totals, averages, summaries.
| Operator | Meaning |
|---|---|
| == | Equal |
| != | Not equal |
| > | Greater than |
| < | Less than |
| >= | Greater or equal |
| <= | Less or equal |
| Operator | Meaning |
|---|---|
| && | AND |
| || | OR |
| ! | NOT |
| Operator | Meaning |
|---|---|
| ~ | Matches pattern |
| !~ | Does not match |
# Name contains "a"
awk -F, '$2 ~ /a/' emp.csv
# Department NOT marketing
awk -F, '$3 ! ~ /marketing/' emp.csv
Key-value storage - like Python dictionaries.
# Count per department
awk -F, 'NR>1 {dept[$3]++} END {for(d in dept) print d, dept[d]}' emp.csv
# Sum salary per city
awk -F, 'NR>1 {city[$5]+=$4} END {for(c in city) print c, city[c]}' emp.csv
Syntax:
array[key] = value # assign
array[key]++ # increment
for(var in array) # loop through keys
| Function | Meaning | Example |
|---|---|---|
| length(s) | String length | length($2) |
| toupper(s) | Uppercase | toupper($2) |
| tolower(s) | Lowercase | tolower($2) |
| substr(s,start,len) | Substring | substr($2,1,3) -> first 3 chars |
| gsub(regex,replace,target) | Global substitute | gsub(/old/,"new",$0) |
| sub(regex,replace,target) | Substitute first match | sub(/old/,"new",$0) |
| split(s,array,sep) | Split string into array | split($0,arr,",") |
| index(s,target) | Find position | index($2,"oh") |
| Function | Meaning |
|---|---|
| int(x) | Integer part |
| sqrt(x) | Square root |
| sin(x), cos(x) | Trigonometry |
| rand() | Random 0-1 |
| srand() | Seed random |
awk -F, '{print $2, $4}' emp.csv
# Output: john 75000
awk -F, '{printf "%-10s %d\n", $2, $4}' emp.csv
# Output: john 75000
| Format | Meaning |
|---|---|
| %s | String |
| %d | Integer |
| %f | Float |
| %-10s | Left-align, 10 chars wide |
| %10s | Right-align, 10 chars wide |
| %.2f | Float with 2 decimals |
| \n | Newline |
| \t | Tab |
awk -F, '{print $2}' emp.csv
awk -F, '{print $2, $4}' emp.csv
awk -F, 'NR==1' emp.csv
awk -F, 'NR>1' emp.csv
awk -F, '{print $NF}' emp.csv
awk -F, '{print $(NF-1)}' emp.csv
awk -F, '$3=="engineering"' emp.csv
awk -F, 'NR>1 && $4>70000 {print $2}' emp.csv
awk -F, '$6=="inactive"' emp.csv
awk -F, '$5=="chicago" || $5=="boston"' emp.csv
awk -F, '$3=="finance" && $4>70000 {print $2}' emp.csv
awk -F, '$2 ~ /a/ {print $2}' emp.csv
awk -F, '$3 ! ~ /marketing/' emp.csv
awk -F, 'NR>1 {print $2":"$4}' emp.csv
awk -F, 'NR>1 {print $2"\t"$3}' emp.csv
awk -F, 'NR>1 {print toupper($2)}' emp.csv
awk -F, 'NR>1 {printf "%-12s %8d\n", $2, $4}' emp.csv
awk -F, 'NR>1 {count++} END {print count}' emp.csv
awk -F, 'NR>1 {dept[$3]++} END {for(d in dept) print d, dept[d]}' emp.csv
awk -F, 'NR>1 {city[$5]++} END {for(c in city) print c, city[c]}' emp.csv
awk -F, 'NR>1 {status[$6]++} END {for(s in status) print s, status[s]}' emp.csv
awk -F, 'NR>1 {sum+=$4} END {print sum}' emp.csv
awk -F, 'NR>1 {sum+=$4; count++} END {print sum/count}' emp.csv
awk -F, 'NR>1 && $4>max {max=$4} END {print max}' emp.csv
awk -F, 'NR>1 {if($4>max){max=$4; name=$2}} END {print name}' emp.csv
awk -F, 'NR==2 {min=$4} NR>2 && $4
awk -F, 'NR>1 {dept[$3]+=$4} END {for(d in dept) print d, dept[d]}' emp.csv
awk -F, 'NR>1 {sum[$5]+=$4; count[$5]++} END {for(c in sum) print c, sum[c]/count[c]}' emp.csv
awk -F, 'NR>1 {sal[NR]=$4; name[NR]=$2; sum+=$4; count++} END {avg=sum/count; for(i in sal) if(sal[i]>avg) print name[i], sal[i]}' emp.csv
awk -F, 'NR>1 {print $4, $2}' emp.csv | sort -rn | head -3
awk -F, 'NR>1 {dept[$3]+=$4} END {for(d in dept) if(dept[d]>max){max=dept[d]; top=d} print top, max}' emp.csv
awk -F, 'NR>1 {print NR-1, $2, $4}' emp.csv
awk -F, 'NR>1 && ! seen[$3]++ {print $3}' emp.csv
awk -F, 'NR>1 {print $2, ($4>75000 ? "HIGH" : "LOW")}' emp.csv
awk -F, 'NR>1 {print $3, $2}' emp.csv
| Task | Command |
|---|---|
| Print column 2 | awk -F, '{print $2}' file |
| Print multiple columns | awk -F, '{print $1, $3}' file |
| Skip header | awk -F, 'NR>1' file |
| Filter by value | awk -F, '$3=="value"' file |
| Filter by number | awk -F, '$4>1000' file |
| Regex match | awk -F, '$2 ~ /pattern/' file |
| Count rows | awk 'END {print NR}' file |
| Sum column | awk -F, '{sum+=$4} END {print sum}' file |
| Average | awk -F, '{sum+=$4} END {print sum/NR}' file |
| Group count | awk -F, '{arr[$3]++} END {for(k in arr) print k, arr[k]}' file |
| Group sum | awk -F, '{arr[$3]+=$4} END {for(k in arr) print k, arr[k]}' file |
| Find max | awk -F, '$4>max {max=$4} END {print max}' file |
| Unique values | awk -F, '! seen[$3]++ {print $3}' file |
| Format output | awk -F, '{printf "%-10s %d\n", $2, $4}' file |
| Mistake | Fix |
|---|---|
| Forgetting -F, for CSV | Specify the delimiter |
| Using = instead of == | = assigns, == compares |
| Spaces around -F | -F, not -F , |
| Wrong quotes | Use single quotes '...' around awk program |
| Forgetting $ for fields | $3 not 3 |
| Multiple END blocks | Only one END {} allowed |
# List all usernames
awk -F: '{print $1}' /etc/passwd
# Find users with bash shell
awk -F: '$7 ~ /bash/ {print $1}' /etc/passwd
# Count requests per IP
awk '{ip[$1]++} END {for(i in ip) print ip[i], i}' access.log | sort -rn | head -10
# Find 404 errors
awk '$9==404 {print $7}' access.log
# Sum sales column
awk -F, 'NR>1 {sum+=$5} END {print "Total Sales:", sum}' sales.csv
# Find above-average performers
awk -F, 'NR>1 {sum+=$5; count++; data[NR]=$0} END {avg=sum/count; for(i in data) {split(data[i],a,","); if(a[5]>avg) print a[1], a[5]}}' sales.csv
grep and sed in pipelinessed notes next
AWK notes complete
Continue with grep, sed, and shell pipelines to make the examples more useful.