Linux awk 命令完全指南:从入门到精通

Linux awk 命令完全指南:从入门到精通

Someone Lv5

引言

在 Linux 文本处理三剑客(grep、sed、awk)中,awk 是最强大但也最有学习曲线的工具。与 grep(搜索过滤)和 sed(流编辑)不同,awk 本质上是一门数据驱动的脚本语言,专门用于格式化处理结构化文本。

awk 的名字来源于其三位创始人:Aho、Weinberger 和 Kernighan。它诞生于 1977 年的贝尔实验室,至今仍是 Unix/Linux 系统中不可或缺的数据处理工具。

本文将全面介绍 awk 的核心概念、基本语法和高级用法,帮助你从入门到精通。

一、awk 的工作原理

理解 awk 的工作模型是掌握它的关键。awk 按行处理文本文件,其基本工作流程如下:

  1. 逐行读取:一次读取输入文件的一行
  2. 字段分割:将每行按分隔符(默认是空白字符)切分成多个字段
  3. 模式匹配:检查该行是否匹配指定的模式
  4. 动作执行:如果模式匹配,执行指定动作
  5. 重复:处理下一行,直到文件结束
1
awk 'pattern { action }' input_file

如果省略 pattern,则对所有行执行 action。如果省略 { action },则默认打印匹配的行(相当于 { print })。

二、基本用法

2.1 字段引用

awk 使用 $1$2$3… 引用第 1、2、3 个字段,$0 表示整行。

1
2
3
4
5
# 打印 /etc/passwd 的第一列(用户名)
awk -F: '{ print $1 }' /etc/passwd

# 打印第 1 和第 3 列
awk -F: '{ print $1, $3 }' /etc/passwd

2.2 内置变量

awk 提供了丰富的内置变量:

变量 说明 示例值
FS 字段分隔符(Field Separator) :,、空格
OFS 输出字段分隔符 默认空格
RS 记录分隔符(Record Separator) 默认换行符 \n
ORS 输出记录分隔符 默认换行符 \n
NR 当前处理的记录编号(行号) 1, 2, 3...
NF 当前记录的字段数量 5, 7...
$0 整条记录(整行) root:x:0:0:root:/root:/bin/bash
$1, $2, ... 第 1、2 个字段 rootx
FILENAME 当前输入文件的名称 passwd

2.3 打印与格式化

1
2
3
4
5
# 打印行号和信息
awk '{ print NR, $1, $NF }' /etc/passwd

# 使用 printf 控制格式
awk -F: '{ printf "%-15s %s\n", $1, $7 }' /etc/passwd

三、模式匹配

3.1 正则表达式

1
2
3
4
5
6
7
8
# 匹配包含 "bash" 的行
awk '/bash/ { print $1 }' /etc/passwd

# 匹配以 "root" 开头的行
awk '/^root/ { print $0 }' /etc/passwd

# 匹配不以 "#" 开头的行(跳过注释)
awk '!/^#/ { print $0 }' config.conf

3.2 关系表达式

1
2
3
4
5
# 打印 UID 大于 500 的用户
awk -F: '$3 > 500 { print $1, $3 }' /etc/passwd

# 打印 GID 不等于 100 的用户
awk -F: '$4 != 100 { print $1, $4 }' /etc/passwd

3.3 范围模式

1
2
3
4
5
# 打印从 "START" 到 "END" 之间的行
awk '/START/, /END/' log.txt

# 打印第 5 到第 10 行
awk 'NR >= 5 && NR <= 10' file.txt

3.4 逻辑运算符

awk 支持 &&(与)、||(或)、!(非)逻辑运算:

1
2
3
4
5
# UID > 100 且 shell 为 /bin/bash
awk -F: '$3 > 100 && $7 == "/bin/bash" { print $1 }' /etc/passwd

# 行号大于 10 且小于 20
awk 'NR > 10 && NR < 20' file.txt

四、高级编程特性

4.1 BEGIN 和 END 块

BEGIN 在所有行处理前执行,END 在所有行处理后执行:

1
2
3
4
5
# 计算文件行数
awk 'BEGIN { count=0 } { count++ } END { print "Total lines:", count }' file.txt

# 计算平均字段数
awk 'BEGIN { total=0 } { total += NF } END { print "Avg fields:", total/NR }' file.txt

4.2 数组

awk 支持关联数组(类似 Python 的 dict 或 JavaScript 的对象):

1
2
3
4
5
6
7
8
9
# 统计各 shell 的使用数量
awk -F: '
{ shells[$7]++ }
END {
for (s in shells) {
print s, shells[s]
}
}
' /etc/passwd

4.3 条件语句

1
2
3
4
5
6
7
8
9
awk -F: '{
if ($3 == 0) {
print $1, "是超级用户"
} else if ($3 < 1000) {
print $1, "是系统用户"
} else {
print $1, "是普通用户"
}
}' /etc/passwd

4.4 循环语句

1
2
3
4
5
6
# 打印每行的所有字段及其编号
awk '{
for (i = 1; i <= NF; i++) {
print "字段" i ":", $i
}
}' file.txt

五、实用示例

5.1 日志分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 统计 Nginx 日志中各状态码的数量
awk '{
status = $9
if (status ~ /^[0-9]+$/) {
codes[status]++
}
}
END {
for (c in codes) {
print c, codes[c]
}
}' /var/log/nginx/access.log

# 找出响应时间超过 5 秒的请求
awk '$NF > 5 { print $1, $7, $NF }' /var/log/nginx/access.log

5.2 CSV 文件处理

1
2
3
4
5
# 处理 CSV 文件(逗号分隔)
awk -F, 'NR > 1 { print $1, $3 }' data.csv

# 计算 CSV 中某列的总和
awk -F, '{ sum += $2 } END { print "总和:", sum }' data.csv

5.3 合并多列输出

1
2
3
4
5
# 将多列合并为一行
awk '{ printf "%s ", $1 } END { print "" }' file.txt

# 按字段排序输出
awk '{ print $1, $2, $3 | "sort -k2" }' data.txt

六、awk 脚本文件

当 awk 程序较长时,可以写入文件执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat calculate.awk
#!/usr/bin/awk -f

BEGIN {
printf "%-10s %10s %10s\n", "名称", "收入", "支出"
total_income = 0
total_expense = 0
}

{
printf "%-10s %10.2f %10.2f\n", $1, $2, $3
total_income += $2
total_expense += $3
}

END {
printf "%-10s %10.2f %10.2f\n", "合计", total_income, total_expense
printf "%-10s %10.2f\n", "结余", total_income - total_expense
}

使用方式:

1
2
3
4
5
6
7
8
$ chmod +x calculate.awk
$ ./calculate.awk finance.txt
名称 收入 支出
工资 15000.00 5000.00
兼职 3000.00 500.00
投资 800.00 2000.00
合计 18800.00 7500.00
结余 11300.00

七、awk 与 grep、sed 配合

实战中,awk 常与其他命令组合使用:

1
2
3
4
5
6
7
8
# 查找错误日志并提取关键字段
grep "ERROR" app.log | awk '{ print $1, $2, $5 }'

# 用 sed 清理数据后传给 awk 分析
sed 's/^[[:space:]]*//' messy.txt | awk '{ print $1, $NF }'

# 管道链:过滤 → 排序 → 格式化
ps aux | awk '$3 > 5.0 { print $2, $3, $11 }' | sort -k2 -rn | head -10

八、常见陷阱与注意事项

  1. 字段分隔符冲突:文件本身包含空格但又想用空格作为分隔符时,连续空格会被当做一个分隔符,这是 awk 的默认行为,通常符合预期
  2. 数值比较:awk 中的变量默认是字符串,但参与算术运算时会自动转为数值
  3. 数组遍历顺序for (k in arr) 的遍历顺序是不确定的
  4. 浮点精度:awk 使用双精度浮点数,精度有限
  5. 大文件处理:awk 是流式处理,内存占用远小于将整个文件读入内存的方案

九、总结

awk 远不止是一个简单的文本处理工具,它是一门小巧而强大的语言。掌握 awk 的核心概念后,你会发现它可以:

  • 快速分析日志文件和系统数据
  • 生成格式化的统计报告
  • 作为 Shell 脚本中的数据处理引擎
  • 处理各种结构化文本格式(CSV、TSV、定宽文件等)

三个实用小技巧记住 awk 的精髓:

  • BEGIN:处理前的初始化
  • body:逐行数据处理(默认块)
  • END:处理后的总结

掌握 grep(搜索)、sed(编辑)、awk(分析)这三剑客,你在 Linux 命令行下的文本处理能力将大大提升。


本文由AI辅助生成,内容仅供参考

  • 标题: Linux awk 命令完全指南:从入门到精通
  • 作者: Someone
  • 创建于 : 2026-06-07 18:35:00
  • 更新于 : 2026-06-18 08:39:57
  • 链接: https://demo-blog.qusite.cn/2026-06-07-awk-command-guide/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。