做什么

awk = 按列处理 + 简单脚本语言。自动把每行切分成 $1 $2 $3 ... 列。

核心:列处理

awk '{print $1}' file.txt           # 第 1 列
awk '{print $1, $3}' file.txt       # 第 1 和 3 列
awk '{print $NF}' file.txt          # 最后一列
awk '{print NR, $0}' file.txt       # 行号 + 整行

内置变量

变量 含义
$0 整行
$1 $2 ... 第 N 列
$NF 最后一列
NF 当前行的列数
NR 当前行号(从 1 起)
FS 输入分隔符(默认空白)
OFS 输出分隔符

条件过滤

awk '$3 > 100' data.txt              # 第 3 列 > 100 的行
awk '/ERROR/ {print $1}' app.log     # 含 ERROR 的行打印第 1 列
awk '$2 == "200"' access.log         # 第 2 列等于 "200"
awk 'NR >= 10 && NR <= 20' file.txt  # 第 10-20 行

自定义分隔符

awk -F',' '{print $2}' data.csv      # CSV:逗号分隔
awk -F':' '{print $1}' /etc/passwd   # /etc/passwd 用 : 分隔
awk 'BEGIN{FS=","; OFS="\t"} {print $1, $3}' data.csv

BEGIN / END

awk 'BEGIN{print "header"} {print} END{print "total:", NR}' file.txt

BEGIN{} 处理前跑一次,END{} 处理完跑一次——很适合做汇总。

实战:常见统计

# 求和(第 1 列)
awk '{sum += $1} END {print sum}' nums.txt

# 平均值
awk '{sum += $1; n++} END {print sum/n}' nums.txt

# 最大值
awk '$1 > max {max = $1} END {print max}' nums.txt

# 分组计数(按第 2 列分组)
awk '{count[$2]++} END {for (k in count) print k, count[k]}' data.txt

# Nginx 日志:最热 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

# Nginx 日志:每个状态码的次数
awk '{print $9}' access.log | sort | uniq -c | sort -rn

# 看 /etc/passwd 里能登录的用户
awk -F: '$7 != "/usr/sbin/nologin" {print $1}' /etc/passwd

  • awk 的列分割按"空白"是默认行为,但多个连续空格当一个分隔符——CSV 等场景必须 -F
  • 大文件 awk 比 sed/grep 慢——简单任务不要用 awk
  • gawk(GNU awk)和 mawk(mini awk)行为略不同——脚本里跨平台要小心