Linux awk 命令:结构化文本处理与数据提取入门
awk 的名字来自三位创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 的姓氏首字母,诞生于 1977 年。与 grep 的"按行匹配"不同,awk 的核心思想是按列处理——它将每一行自动拆分成多个字段(列),然后对指定列执行操作。这使得 awk 在处理表格化数据(如日志、CSV、ps/df/netstat 等命令输出)时格外高效。
最基础的用法
awk '{print $1, $2}' file.txt
$1、$2分别代表第 1 列、第 2 列,$0代表整行。- 默认以空白字符(空格或 Tab)作为分隔符。
print是 awk 最基本的动作,输出指定内容。
实际使用中,高频场景与命令组合
1. 指定分隔符
awk -F':' '{print $1, $3}' /etc/passwd
-F 指定字段分隔符。/etc/passwd 用冒号分隔,这条命令输出用户名(第 1 列)和 UID(第 3 列)。
处理 CSV 文件:
awk -F',' '{print $1, $5}' data.csv
2. 条件过滤
awk -F':' '$3 >= 1000 {print $1}' /etc/passwd
只输出 UID ≥ 1000 的普通用户名。awk 的条件写在 {} 前面,语法类似 C 语言。
3. 内置变量
| 变量 | 含义 |
|---|---|
NR |
当前行号(全局) |
FNR |
当前文件的行号(多文件时各自计数) |
NF |
当前行的字段数(列数) |
FS |
输入分隔符(同 -F) |
OFS |
输出分隔符(默认空格) |
# 输出第 5~10 行
awk 'NR>=5 && NR<=10' file.txt
# 输出每行的列数
awk '{print NR, NF}' file.txt
# 只输出列数大于 3 的行
awk 'NF > 3' file.txt
4. 统计计算
# 求第 2 列的总和
awk '{sum += $2} END {print sum}' file.txt
# 求平均值
awk '{sum += $2; count++} END {print sum/count}' file.txt
# 统计某列各值出现次数
awk '{count[$1]++} END {for (k in count) print k, count[k]}' file.txt
END 块在所有行处理完后执行,适合做汇总统计。
5. 格式化输出
awk '{printf "%-15s %8d\n", $1, $2}' file.txt
printf 支持 C 风格的格式化:%-15s 左对齐 15 字符宽的字符串,%8d 右对齐 8 字符宽的整数。比 print 更灵活。
6. 处理命令输出
# 查看占用内存最多的前 5 个进程
ps aux | awk '{print $2, $4, $11}' | sort -k2 -rn | head -5
# 统计 Nginx 访问日志中各状态码的数量
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 提取所有监听中的端口
ss -tlnp | awk 'NR>1 {print $4}' | grep -oP ':\K\d+$' | sort -un
7. 多文件处理
awk 'FNR==NR {a[$1]=$2; next} {print $1, a[$1]}' file1.txt file2.txt
这是一个经典模式:先读 file1.txt 建立查找表(数组 a),再读 file2.txt 时根据第 1 列查表输出。相当于用 awk 实现了简单的 join 操作。
8. BEGIN 和 END 块
awk 'BEGIN {FS=","; OFS="\t"; print "Name\tScore"}
{print $1, $2}
END {print "---"; print "Total lines:", NR}' data.csv
BEGIN块在读取任何行之前执行,适合初始化变量、打印表头。END块在所有行处理完后执行,适合输出汇总信息。
9. 字符串函数
# 转大写
awk '{print toupper($1)}' file.txt
# 提取子串
awk '{print substr($1, 1, 5)}' file.txt
# 替换
awk '{gsub(/old/, "new", $0); print}' file.txt
# 长度
awk 'length($1) > 10' file.txt
10. 条件表达式
awk '{status = ($2 >= 60) ? "PASS" : "FAIL"; print $1, status}' scores.txt
支持三元运算符、if-else 等流程控制。
如果不知道如何下手,可以先尝试
df -h | awk '{print $1, $5, $6}'
这条命令从 df -h 的输出中提取文件系统、使用率和挂载点三列,快速查看磁盘使用情况。确认输出符合预期后,可以进一步加条件过滤:
df -h | awk 'NR>1 && int($5) > 80 {print $6, $5}'
找出使用率超过 80% 的分区。
或者,当你想快速统计 Nginx 日志中每个 IP 的访问次数时:
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' /var/log/nginx/access.log | sort -rn | head -10
awk 与相关工具对比
| 工具 | 特点 | 适用场景 |
|---|---|---|
grep |
按行匹配 | 过滤包含某关键词的行 |
cut |
按列提取 | 简单列提取,不支持计算 |
awk |
按列处理 + 计算 | 结构化数据的提取、统计、格式化 |
sed |
按行替换/编辑 | 文本替换、插入、删除 |
三者常配合使用:grep 过滤行 → awk 提取列 → sort | uniq 统计。
- 点赞
- 收藏
- 关注作者
评论(0)