Linux 文本处理三剑客:awk 使用教程

介绍

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 坑提醒

  1. 字符串比较 $3=="male",​双引号​,不要漏
  2. 等号判断是 ==,单个=是赋值
  3. 正则 /pattern/ 斜杠包裹
  4. 多个动作要用分号隔开,或者换行
  5. 字段默认分割:连续多个空格视为1个分隔符

原文出处:/show_1GW42gw9TSBK.html