当前位置:首页>Linux>Linux 四剑客之 awk:取行取列 + 分隔符 + 条件判断 + 统计计算 | 11 个实战案例一次吃透

Linux 四剑客之 awk:取行取列 + 分隔符 + 条件判断 + 统计计算 | 11 个实战案例一次吃透

  • 2026-10-11 08:23:42
Linux 四剑客之 awk:取行取列 + 分隔符 + 条件判断 + 统计计算 | 11 个实战案例一次吃透
在 Linux 四剑客中,find 擅长找文件,grep 擅长过滤,sed 擅长替换,而 awk 则是当之无愧的"全能王"——它不仅能过滤、取行,更能取列、统计计算、条件判断,甚至支持循环和数组。严格来说,awk 不仅是一个命令,更是一门单行脚本语言。

本文从基础格式讲到统计计算,配合 11 个实战案例,帮你彻底掌握 awk 这把最强利器。


一、四剑客定位对比

剑客核心特长擅长场景
find查找文件按名称/大小/时间定位文件,与其他命令配合
grep / egrep过滤过滤速度最快,快速定位包含关键字的行
sed替换、取行批量替换文本、修改文件内容
awk取列、统计计算取行取列、条件判断、统计求和、格式化输出

awk 的核心优势在于列处理能力——其他三个剑客都无法直接按列提取和运算。


二、awk 基本格式

awk [选项] '条件{动作}' 文件
  • 条件:找谁(哪些行满足要求)

  • 动作:干啥(对满足条件的行做什么操作)

示例: 取出 /etc/passwd 第 1 行的第 1 列、第 3 列和最后一列:

awk -F: 'NR==1{print $1,$3,$NF}' /etc/passwd#   选项   条件    动作            文件

执行流程

awk 逐行读取文件      │      ▼  当前行是否满足条件?      │  ┌───┴───┐  是      否  │       │  ▼       ▼执行动作  跳过,读下一行  │  ▼输出结果

三、取行

案例 1:取出指定行

# 取出 /etc/passwd 的第 1 行awk 'NR==1'  /etc/passwd# 输出:root:x:0:0:root:/root:/bin/bash

知识点解析:

元素含义
NRNumber of Record,记录号(即行号)
==等于
{print $0}输出整行内容($0 表示当前行),满足条件后的默认动作,可省略

案例 2:取出范围行

# 取出第 2 行到第 5 行awk 'NR>=2 && NR<=5' /etc/passwd

awk 常用运算符

运算符说明示例
==等于NR==1
!=不等于NR!=1
>大于$3>100
>=大于等于NR>=2
<小于$3<100
<=小于等于NR<=5
&&并且(AND)NR>=2 && NR<=5
\|\|或者(OR)NR==1 \|\| NR==3
!取反(NOT)!/root/

案例 3:按内容过滤行

# 过滤出包含 root 或 nobody 的行awk '/root|nobody/' /etc/passwd

案例 4:范围过滤

# 从包含 root 的行到包含 nobody 的行(包含首尾)awk '/root/, /nobody/' /etc/passwd

取行小结

方法说明示例
NR==N取指定行awk 'NR==1'
NR>=M && NR<=N取范围行awk 'NR>=2 && NR<=5'
/正则/过滤包含内容的行awk '/root/'
/开始/,/结束/范围过滤awk '/root/,/nobody/'

四、取列

这是 awk 最核心的能力,也是区别于其他工具的关键。

案例 5:取出指定列

# 取出 ls -lh 结果的大小列(第5列)和文件名列(最后一列)ls -lh /etc/hosts | awk '{print $5,$NF}'# 输出:158 /etc/hosts

列相关的变量:

变量含义
$1第 1 列
$2第 2 列
$N第 N 列
$0整行内容
$NF最后一列(NF = Number of Field,字段总数)
$(NF-1)倒数第 2 列
NF当前行的列数

实用示例: 从安全日志中提取密码错误的 IP 地址:

grep 'Failed' /var/log/secure | awk '{print $(NF-3)}'

输出对齐

awk 输出多列时默认用空格分隔,可以用以下方式对齐:

# 方法一:使用 column 命令对齐ls -lh | awk '{print $5,$NF}' | column -t# 方法二:使用 \t(Tab)分隔ls -lh | awk '{print $5"\t"$NF}' 

案例 6:指定分隔符取列

awk 默认以空白字符(空格、连续空格、Tab)为分隔符。对于 /etc/passwd 这种以冒号分隔的文件,需要用 -F 手动指定:

# 取出用户名(第1列)、UID(第3列)和 Shell(最后一列)awk -F ':' '{print $1,$3,$NF}'  /etc/passwd | column -t

分隔符选择技巧: 看你想取的目标字段两边是什么字符,那个字符就是分隔符。

案例 7:复杂分隔符提取 IP 地址

这是 awk 的经典面试题——从 ip a 输出中提取 IP 地址:

# 原始数据(第3行)ip a s eth0 | awk 'NR==3'#     inet 192.168.2.200/24 brd 192.168.2.255 scope global eth0

方法一:逐步拆解(初学者思路)

ip a s eth0 | awk 'NR==3' | awk '{print $2}' | awk -F '/''{print $1}'# 192.168.2.200

方法二:使用字符类分隔符

# [ /] 表示遇到空格或 / 就切一刀(4个空格切4刀,IP 在第6列)ip a s eth0 | awk 'NR==3' | awk -F '[ /]''{print $6}'# [ /]+ 表示遇到连续的空格或 / 切一刀(4个空格切1刀,IP 在第3列)ip a s eth0 | awk 'NR==3' | awk -F '[ /]+''{print $3}'

方法三:使用字符串分隔符

# 用 "inet " 和 "/24" 作为分隔符,IP 在第2列ip a s eth0 | awk 'NR==3' | awk -F 'inet |/24''{print $2}'

分隔符小结

场景做法
空格/Tab 分隔直接取列,无需 -F
固定字符分隔(如 :;)-F':'
多种字符分隔-F'[ /]'(字符类)
连续分隔符合并-F'[ /]+'(加 + 号)
字符串分隔-F'inet \|/24'(用 \| 分隔多个字符串)

五、取行 + 取列

真正的实战中,取行和取列通常需要组合使用。

案例 8:一步到位提取 IP

# 条件:第3行  动作:取第3列  分隔符:连续空格或/ip a s eth0 | awk -F '[ /]+''NR==3{print $3}'# 192.168.2.200

额外示例: 提取文件权限的数字部分(如 0644):

stat  /etc/hosts | awk -F '[/(]''NR==4{print $2}'# 或者用非数字作为分隔符stat  /etc/hosts | awk -F '[^0-9]+''NR==4{print $2}'

案例 9:按列的值过滤行

取出 /etc/passwd 中 UID 大于 100 的用户,显示用户名、UID 和 Shell:

# 只看条件awk -F ':' '$3>=100' /etc/passwd# 条件 + 动作awk -F ':' '$3>=100{print $1,$3,$NF}' /etc/passwd | column -t

这就是 awk 的威力——对某一列进行数值比较和过滤,grep 和 sed 做不到。

案例 10:多条件组合判断

检查系统 swap 使用情况:

# 条件:Swap 行 且 第3列(已使用)大于 0 free | awk '/Swap/ && $3>0 {print "Warning: swap is being used!"}'

案例 11:对某一列进行正则匹配

取出 /etc/passwd 中第 4 列(GID)以 0 或 1 开头的行:

awk -F ':' '$4 ~ /^[01]/ {print $1,$3,$4}' /etc/passwd

列匹配操作符:

操作符含义示例
~包含(正则匹配)$1 ~ /root/ 第1列包含 root
!~不包含$1 !~ /nologin/ 第1列不包含 nologin

六、统计与计算

awk 的计算能力是它被称为"语言"的重要原因。

BEGIN 与 END

块执行时机用途
BEGIN{}读取文件之前执行一次初始化变量、打印表头
{...}每读取一行执行一次主逻辑
END{}读取完所有行后执行一次输出汇总结果
awk 'BEGIN{print "开始处理"} {处理每一行} END{print "处理完成"}' file

统计行数(计数)

原理:i=i+1,每读一行 i 加 1,最后输出 i:

# 统计 /etc/passwd 有多少行(等效于 wc -l)awk '{i=i+1}  END {print i}'  /etc/passwd# 26# 简写awk 'END{print NR}'  /etc/passwd# 26

计算过程演示:

行数i 的初始值执行 i=i+1i 的最终值
第 1 行0(空/未定义)i=0+11
第 2 行1i=1+12
第 3 行2i=2+13
............
第 N 行N-1i=(N-1)+1N

求和

# 统计 /etc/passwd 中所有用户 UID 的总和awk -F ':' '{sum=sum+$3} END{print sum}'  /etc/passwd# 简写为 +=awk -F  ':' '{sum+=$3} END{print sum}'  /etc/passwd

求平均值

# 所有用户 UID 的平均值awk -F ':' '{sum+=$3}  END{print sum/NR}' /etc/passwd

补充:条件统计

# 统计 UID 大于 100 的用户有多少个awk -F':' '$3>100{count++}  END{print count}'  /etc/passwd# 统计 /var/log/ 下所有 .log 文件的总大小ls -l  /var/log/*.log | awk '{sum+=$5}  END{print sum/1024/1024" MB"}'

补充:数组统计(进阶)

awk 数组是统计分析的利器,最经典的应用是统计每个元素出现的次数:

# 统计每个 Shell 被多少用户使用awk -F ':' '{shell[$NF]++}  END {for(s in shell) print s, shell[s]}'  /etc/passwd# /bin/bash 3# /sbin/nologin 18# /bin/sync 1# 统计 Nginx 日志中每个 IP 的访问次数,取 Top 10awk '{ip[$1]++} END{for(i in ip) print ip[i], i}'  access.log | sort-rn | head -10

七、补充:awk 内置变量速查

变量含义
NR当前行号(Number of Record)
NF当前行的列数(Number of Field)
$0当前行的全部内容
$N第 N 列
$NF最后一列
FS输入字段分隔符(等效于 -F,默认空白)
OFS输出字段分隔符(默认空格)
RS输入记录分隔符(默认换行)
ORS输出记录分隔符(默认换行)
FILENAME当前处理的文件名
FNR当前文件的行号(处理多文件时有用)

OFS 示例: 控制输出分隔符:

# 用逗号分隔输出(生成 CSV)awk -F ':' 'BEGIN{OFS=","} {print $1,$3,$NF}'  /etc/passwd# root,0,/bin/bash# bin,1,/sbin/nologin

八、补充:格式化输出 printf

print 输出简单但格式不可控,printf 可以精确控制格式:

# 格式化输出用户名和 UID,左对齐,固定宽度awk -F ':' '{printf "%-15s %-6s %s\n", $1, $3, $NF}' /etc/passwd# root            0      /bin/bash# bin             1      /sbin/nologin
格式符含义
%s字符串
%d整数
%f浮点数
%-15s左对齐,宽度 15 的字符串
\n换行(printf 不自动换行)

九、知识体系总结

awk '条件{动作}' 文件         │      │         │      ├── print $1,$3,$NF       取列         │      ├── print $0              输出整行         │      ├── i++; sum+=$3       统计计算         │      └── printf "%-10s", $1  格式化输出         │         ├── NR==1                         取指定行         ├── NR>=2 && NR<=5     取范围行         ├── /root/                        正则过滤行         ├── $3>=100                       按列值过滤         └── $4 ~ /^[01]/                  按列正则匹配选项:-F':'           指定分隔符特殊块:BEGIN{}        读取前执行       END{}          读取后执行

掌握优先级:

  1. 核心:取行(NR)与取列($N, $NF)

  2. 熟练:对列进行数值比较($3>=100)

  3. 熟悉:对列进行正则匹配($4 ~ /^[01]/)

  4. 进阶:统计计算(计数、求和、数组统计)


写在最后

至此,Linux 四剑客系列已全部集结:

篇目核心能力一句话总结
find查找文件按名称/大小/时间精准定位,三种组合技配合其他命令
grep过滤文本速度最快的行过滤工具,正则表达式的最佳搭档
sed替换修改流编辑器,批量替换文本内容的瑞士军刀
awk取列计算最强文本处理语言,取列+统计+判断无所不能

四剑客各有所长,组合使用威力倍增。掌握它们,日常运维中 90% 的文本处理需求都能轻松应对。

关注本公众号,更多 Linux 实战内容持续更新。

觉得有用?转发给你的运维/开发同事,一起修炼内功。

最新文章

随机文章