awk 的强大之处在于它既是一个文本处理工具,又是一门轻量级脚本语言。它原生支持字段分割、条件过滤、循环控制和数据统计,让你在一个命令里就能完成从数据提取到报表输出的完整流程。
1. 字段处理
awk 会默认按空白字符(空格或制表符)将每一行分割成多个字段,分别用 $1、$2、$3... 表示。$0 代表整行。你可以通过 -F 选项指定自定义分隔符,也可以在脚本中修改 FS 变量。
示例数据(保存为 users.txt):
张三 研发部 12000 3
李四 市场部 9000 5
王五 研发部 15000 7
- 只打印姓名和部门:
awk '{print $1, $2}' users.txt
- 处理 CSV 文件(用逗号分隔):
awk -F, '{print $3}' data.csv
- 处理类似
key=value的配置文件:
awk -F= '{print "Key:", $1, "Value:", $2}' config.txt
- 用
NF(字段数量)和$NF(最后一个字段):
awk '{print $1, $NF}' users.txt # 打印姓名和最后一列(工龄)
2. 条件判断
awk 支持类似 C 语言的 if、关系运算符和正则匹配,可以灵活地筛选行或控制计算逻辑。
- 按条件过滤行:打印研发部且工资大于 10000 的员工
awk '$2 == "研发部" && $3 > 10000 {print $1, $3}' users.txt
- 正则匹配:打印姓名中包含“王”的记录
awk '$1 ~ /王/ {print $0}' users.txt
if...else语句:对工资分段标注
awk '{
if ($3 > 12000) level = "高"
else level = "普通"
print $1, $3, level
}' users.txt
- 三元运算符:简洁的条件赋值
awk '{print $1, ($3 > 12000 ? "高薪" : "正常")}' users.txt
- 范围模式:打印从包含“李四”到包含“王五”之间的所有行
awk '/李四/,/王五/' users.txt
3. 循环
awk 提供 for、while 循环,既可以遍历字段,也可以处理数据块。
- 遍历每一行中的所有字段:
awk '{for(i=1;i<=NF;i++) printf "[%s] ", $i; print ""}' users.txt
- 累计求和:计算所有员工的总工资
awk '{sum += $3} END {print "总工资:", sum}' users.txt
- 循环配合数组去重:收集所有出现过的部门
awk '{departments[$2]++}
END {for(d in departments) print d}' users.txt
4. 统计聚合
awk 最实用的场景之一就是即时生成统计报表。结合数组、条件判断和 END 块,可以轻松实现分组、求和、平均值、计数、最大值等操作。
- 按部门统计人数和平均工资:
awk '{
cnt[$2]++; total[$2] += $3
}
END {
for(d in cnt)
printf "部门: %s, 人数: %d, 平均工资: %.2f\n", d, cnt[d], total[d]/cnt[d]
}' users.txt
- 同时计算总和、平均值、最大值、最小值:
awk '{
sum += $3
if ($3 > max) max = $3
if (min == 0 || $3 < min) min = $3
count++
}
END {
printf "总和: %d, 平均值: %.2f, 最大值: %d, 最小值: %d\n", sum, sum/count, max, min
}' users.txt
- 按字段统计频次(类似
sort | uniq -c):
awk '{count[$2]++} END {for(dept in count) print dept, count[dept]}' users.txt
- 累加计算(如累计工资):
awk '{sum += $3; print $1, "累计工资:", sum}' users.txt
实用技巧总结
- 字段处理:善用
-F分隔符和$1、$NF、NF变量。 - 条件判断:将模式和
if灵活搭配,正则让匹配更精准。 - 循环:多在
END块中与数组结合做分组统计。 - 统计聚合:数组下标作为分类键,值存放计数或累加量,再用
END一次性输出。
掌握这四项能力,你的 awk 脚本就能从“简单过滤”进阶到“数据清洗与报表生成”的利器,绝大多数命令行实时分析需求都可以在一行内解决。