介绍
awk 是文本处理神器,核心:按行读取文本,按字段分割,匹配条件后执行动作
awk 执行流程:读一行 → 分割字段($1,$2...) → 判断条件 → 执行{}内代码;内置变量:
$0整行,NR行号,NF当前行字段总数,FS输入分隔符,OFS输出分隔符
一、基础语法
awk [选项] '条件{动作}' 文件名
- 选项:
-F指定输入分隔符(默认空格/制表符) - 条件:比如
NR>2、$3=="male",省略条件=匹配所有行 - 动作:放在
{}里,print打印;省略动作=print $0打印整行
二、准备测试文件
复制下面全部内容,保存为 test.txt,直接用来练习
# test.txt
zhangsan 25 male 88
lisi 22 female 92
wangwu 28 male 76
zhaoliu 24 female 95
qianqi 30 male 59
sunba 27 female 81
zhoujiu 26 male 72
创建命令:
cat > test.txt <<'EOF'
zhangsan 25 male 88
lisi 22 female 92
wangwu 28 male 76
zhaoliu 24 female 95
qianqi 30 male 59
sunba 27 female 81
zhoujiu 26 male 72
EOF
字段说明:姓名 年龄 性别 分数
三、基础示例(直接复制运行)
1. 打印全部行(等价 cat)
awk '{print $0}' test.txt
# 简写,无动作默认打印整行
awk '' test.txt
2. 打印第1列(姓名)、第4列(分数)
awk '{print $1,$4}' test.txt
$1第一个字段,$2第二个,以此类推
3. 自定义输出格式,加字符串
awk '{print "姓名:"$1,"分数:"$4}' test.txt
4. 内置变量 NR(行号),打印行号+内容
awk '{print NR,$0}' test.txt
5. NF:当前行有多少个字段;打印最后一列 $NF
# 打印每行字段数量,以及最后一列
awk '{print NF, $NF}' test.txt
6. 条件过滤:只打印男性($3等于male)
字符串比较必须双引号;
==等于,!=不等于
awk '$3=="male"{print $1,$2,$4}' test.txt
7. 数值比较:年龄大于25岁的人
awk '$2>25{print $0}' test.txt
8. 多条件 && 并且 / || 或者
# 男性,并且分数大于80
awk '$3=="male" && $4>80 {print $0}' test.txt
# 或者:分数大于90 或者 小于60
awk '$4>90 || $4<60 {print $0}' test.txt
9. 匹配正则 ~ 包含;!~ 不包含
# 姓名包含 zhang 的行
awk '$1 ~ /zhang/ {print $0}' test.txt
# 姓名不包含 zhou
awk '$1 !~ /zhou/ {print $0}' test.txt
四、BEGIN / END 块
BEGIN{}:读取文件之前执行一次,一般用于打印表头、设置分隔符END{}:全部文件读完之后执行一次,统计总和、平均值
# 示例:统计所有人总分、平均分
awk '
BEGIN{
print "====成绩统计===="
total=0
count=0
}
{
total += $4
count++
}
END{
print "总人数:"count
print "总分:"total
print "平均分:" total/count
}
' test.txt
五、分隔符 -F
默认分隔符是空格/多个空格/tab;-F 修改输入分隔符
新建一个逗号分隔文件 test.csv
cat > test.csv <<'EOF'
zhangsan,25,male,88
lisi,22,female,92
wangwu,28,male,76
EOF
用逗号分割:
awk -F ',' '{print $1,$4}' test.csv
也可以在BEGIN里设置FS:
awk 'BEGIN{FS=","}{print $1,$4}' test.csv
OFS:输出分隔符
awk 'BEGIN{FS=",";OFS="|"}{print $1,$4}' test.csv
# 输出:zhangsan|88
六、if 判断,for循环
if 示例:分数评级
awk '{
if($4 >=90){
level="A"
}else if($4 >=80){
level="B"
}else if($4 >=60){
level="C"
}else{
level="D"
}
print $1,$4,level
}' test.txt
for循环:遍历字段
# 循环打印一行里所有字段
awk '{for(i=1;i<=NF;i++) print "第"i"列:"$i}' test.txt
七、常用内置变量汇总
| 变量 | 含义 |
|---|---|
| $0 | 整行文本 |
| $1,$2... | 第1、2...个字段 |
| NR | 已经读取的总行号(多个文件会累加) |
| FNR | 当前文件行号(多文件时重新计数) |
| NF | 当前行字段个数 |
| FS | 输入分隔符,默认空白 |
| OFS | 输出分隔符,默认空格 |
| RS | 输入行分隔符(默认换行) |
| ORS | 输出行分隔符(默认换行) |
NR vs FNR 例子,同时读取两个文件
awk '{print NR,FNR,$0}' test.txt test.csv
八、数组(awk 关联数组,类似字典)
统计男女数量
awk '
BEGIN{print "性别统计"}
{
sex[$3]++
}
END{
for(k in sex){
print k, sex[k]
}
}
' test.txt
输出:
性别统计
male 4
female 3
九、awk 坑提醒
- 字符串比较
$3=="male",双引号,不要漏 - 等号判断是
==,单个=是赋值 - 正则
/pattern/斜杠包裹 - 多个动作要用分号隔开,或者换行
- 字段默认分割:连续多个空格视为1个分隔符