一、环境准备
创建测试文件 students.txt:
bash
cat > students.txt << EOF
1|张三|男|90|85|92
2|李四|女|88|92|89
3|王五|男|95|88|94
4|赵六|女|92|96|91
5|孙七|男|87|84|86
EOF
创建另一个测试文件 data.txt:
bash
cat > data.txt << EOF
apple 5 2.5
banana 3 1.2
orange 8 3.0
grape 12 4.5
EOF
二、基础练习
练习1:打印整行
bash
#打印所有行
awk '{print}' students.txt
# 打印包含"女"的行
awk '/女/' students.txt
练习2:打印指定字段
bash
# 打印第1列和第3列(默认分隔符为空格或制表符)
awk '{print $1, $3}' data.txt
# 使用 -F 指定分隔符为 |
awk -F'|' '{print $2, $3}' students.txt
# 打印最后一列
awk '{print $NF}' data.txt
练习3:格式化输出
bash
# 格式化输出
awk -F'|' '{printf "姓名:%s,性别:%s\n", $2, $3}' students.txt
# 对齐输出
awk -F'|' '{printf "%-6s %-2s\n", $2, $3}' students.txt
三、进阶练习
练习4:数学运算
bash
# 计算每行总和(data.txt第2列*第3列)
awk '{print $1, $2 * $3}' data.txt
# 计算学生平均分(students.txt第4-6列)
awk -F'|' '{sum=$4+$5+$6; avg=sum/3; print $2, "总分:"sum, "平均:"avg}' students.txt
练习5:使用变量和条件判断
bash
# 找出平均分>=90的学生
awk -F'|' '{avg=($4+$5+$6)/3; if(avg>=90) print $2, avg}' students.txt
# 多条件:女学生且平均分>90
awk -F'|' '{avg=($4+$5+$6)/3; if($3=="女" && avg>90) print $2, avg}' students.txt
# 使用 case 语句
awk -F'|' '{
if($4>=90) grade="优秀"
else if($4>=80) grade="良好"
else grade="及格"
print $2, $4, grade
}' students.txt
练习6:BEGIN 和 END 块
bash
# 统计行数、总分数
awk -F'|' 'BEGIN{print "姓名\t总分"; sum=0}
{total=$4+$5+$6; print $2"\t"total; sum+=total}
END{print "总分数:"sum, "平均:"sum/NR}' students.txt
# 添加表头
awk 'BEGIN{print "====== 学生成绩表 ======"; print "姓名\t语文\t数学\t英语"}
-F'|' '{print $2"\t"$4"\t"$5"\t"$6}
END{print "====== 共"NR"人 ======"}' students.txt
四、内置变量练习
练习7:常用内置变量
bash
# NR: 行号,NF: 字段数
awk '{print "行号:"NR, "字段数:"NF, "内容:"$0}' data.txt
# 打印奇数行
awk 'NR%2==1' students.txt
# 打印第2-4行
awk 'NR>=2 && NR<=4' students.txt
# 打印字段数大于3的行
awk -F'|' 'NF>3' students.txt
五、实战综合练习
练习8:文本处理
bash
# 去重
awk '!seen[$0]++' file.txt
# 统计重复行次数
awk '{count[$0]++} END{for(line in count) print count[line], line}' file.txt
# 按列求和
awk '{sum+=$2} END{print "总和:"sum, "平均值:"sum/NR}' data.txt
# 找出最大值
awk 'NR==1{max=$2} $2>max{max=$2} END{print "最大值:"max}' data.txt
练习9:复杂数据处理
bash
# 分组统计(按性别统计平均分)
awk -F'|' '{sum[$3]+=$4+$5+$6; count[$3]++}
END{for(sex in sum) print sex, "平均分:"sum[sex]/count[sex]/3}' students.txt
# 输出到不同文件
awk -F'|' '{if($3=="男") print > "boys.txt"; else print > "girls.txt"}' students.txt
六、综合应用
题目1:日志分析
假设有日志文件 access.log:
text
192.168.1.1 - - [01/Jan/2024:10:00:01] "GET /index.html" 200
192.168.1.2 - - [01/Jan/2024:10:00:02] "POST /api" 404
192.168.1.1 - - [01/Jan/2024:10:00:03] "GET /about" 200
bash
# 统计每个IP的访问次数
awk '{count[$1]++} END{for(ip in count) print ip, count[ip]}' access.log
# 统计HTTP状态码分布
awk '{status=$NF; count[status]++} END{for(code in count) print code, count[code]}' access.log
题目2:CSV 文件处理
bash
# 转换分隔符(| 转成逗号)
awk -F'|' -v OFS=',' '{$1=$1; print}' students.txt > students.csv
# 多文件处理
awk 'NR==FNR{arr[$1]=$2; next} {print $0, arr[$1]}' file1.txt file2.txt
七、语法参考表
需求 awk命令
打印第n列 awk '{print $n}'
指定分隔符 awk -F','
行号 NR
字段数 NF
最后一列 $NF
条件过滤 awk '$3>90'
行范围 awk 'NR>=2 && NR<=5'
求和 awk '{sum+=$2} END{print sum}'
计数 awk '{count++} END{print count}'
去重 awk '!seen[$0]++'
格式化输出 awk '{printf "%-10s\n", $1}'