awk
是 Linux/Unix 系统中功能强大的文本处理工具,擅长对数据进行格式化输出、统计分析、过滤筛选等操作。它以“行”为基本处理单位,结合内置变量、函数和自定义逻辑,能高效处理结构化数据(如日志、CSV、表格等)。以下是系统的 awk
学习指南:
一、基本语法
awk [选项] '模式 {动作}' [输入文件]
-
选项:常用
-F
(指定字段分隔符)、-v
(定义变量)。 -
模式:用于筛选符合条件的行(如行号、正则匹配、逻辑表达式)。
-
动作:对匹配行执行的操作(如打印字段、计算、调用函数)。
二、核心概念:字段与内置变量
1. 字段分割
-
默认以空格/制表符为分隔符,将每行拆分为字段(
field
),用$1
、$2
...$n
表示第 1 到第 n 个字段,$0
表示整行。 -
用
-F
选项自定义分隔符:
awk -F',' '{print $1, $3}' data.csv # 以逗号分隔,打印第1和第3列
awk -F': ' '{print $1}' /etc/passwd # 以": "分隔,打印用户名列
2. 内置变量
变量 | 说明 |
---|---|
NF | 每行的字段数(Number of Fields) |
NR | 已处理的行号(行号从 1 开始,全局唯一) |
FNR | 各文件的行号(适用于多文件输入,每个文件独立计数) |
FS | 字段分隔符(Field Separator),默认值为空格/制表符 |
OFS | 输出字段分隔符(Output Field Separator),默认值为空格 |
RS | 行分隔符(Record Separator),默认值为换行符 \n |
ORS | 输出行分隔符(Output Record Separator),默认值为换行符 \n |
三、基础用法:模式与动作
1. 简单打印
- 打印所有行:
awk '{print}' file.txt # 等价于 cat file.txt
- 打印指定字段:
echo "apple,banana,cherry" | awk -F',' '{print $1, $3}' # 输出: apple cherry
2. 按条件筛选行(模式匹配)
- 正则匹配:
awk '/error/' access.log # 打印包含"error"的行
awk '$2 ~ /^[0-9]/' data.txt # 打印第2字段以数字开头的行(~ 表示匹配)
- 逻辑表达式:
awk '$3 > 100' sales.csv # 打印第3列数值大于100的行
awk '$1 == "user1" && $4 < 50' users.txt # 同时满足两个条件的行
3. 格式化输出
- 使用
OFS
自定义输出分隔符:
awk -F',' 'BEGIN{OFS="|"} {print $1, $2}' data.csv # 输出字段用"|"分隔
- 格式化字符串(类似 C 语言的
printf
):
awk -F',' '{printf "姓名: %-10s 分数: %d\n", $1, $2}' scores.txt
四、流程控制与高级语法
1. 条件语句 if-else
awk -F',' '{
if ($3 > 80) {
print $1, "优秀"
} else if ($3 >= 60) {
print $1, "及格"
} else {
print $1, "不及格"
}
}' scores.txt
2. 循环语句 for/while
- 遍历字段:
awk '{for (i=1; i<=NF; i++) print $i}' file.txt # 逐行打印每个字段
- 数值循环:
awk 'BEGIN{for (i=1; i<=5; i++) sum += i; print "总和:", sum}' # 输出: 总和: 15
3. 数组(Associative Array)
用于统计重复项或分组数据:
# 统计单词出现次数
awk '{
for (i=1; i<=NF; i++) {
word = $i
count[word]++ # 数组下标为单词,值为出现次数
}
} END{
for (word in count) {
print word, count[word]
}
}' text.txt
五、特殊模式:BEGIN 和 END
-
BEGIN
:在处理文件前执行(常用于初始化变量、设置分隔符)。 -
END
:在处理完所有文件后执行(常用于输出统计结果)。
示例:
# 计算文件行数和平均字段数
awk '
BEGIN{
FS="," # 设置输入分隔符为逗号
print "开始处理..."
}
{
line_count++
field_count += NF
}
END{
avg = field_count / line_count
print "总行数:", line_count
print "平均字段数:", avg
}
' data.csv
六、实战案例
1. 日志分析
- 统计各IP的访问次数:
awk '{ip[$1]++} END{for(i in ip) print i, ip[i]}' access.log
- 提取特定时间段的日志:
awk '$4 ~ /May\/2025/ {print $0}' access.log # 提取2025年5月的日志
2. 数据统计
- 计算销售额总和(CSV文件,第3列为金额):
awk -F',' '{sum += $3} END{print "总销售额:", sum}' sales.csv
- 按部门分组统计人数:
awk -F',' '{dept[$2]++} END{for(d in dept) print d, dept[d]}' employees.csv
3. 格式转换
- 将 CSV 转换为 JSON:
awk -F',' '
BEGIN{
print "["
OFS='","'
}
{
print " {\"姓名\":\""$1"\",\"年龄\":\""$2"\",\"分数\":\""$3"\"}"
}
END{
print "]"
}
' scores.csv
七、常用技巧与注意事项
- 正则表达式:
- 使用 ~
(匹配)或 !~
(不匹配),支持扩展正则(需加 -r
选项):
awk -r '$1 ~ /^[0-9]{3}-[0-9]{4}/' phone.txt # 匹配3位区号-4位号码
- 变量传递:
- 从 shell 传递变量到 awk:
threshold=80
awk -v thr=$threshold '$3 > thr {print $1}' scores.txt
- 多文件处理:
bash awk 'NR==FNR {count++} END {print "文件数:", count}' file1.txt file2.txt file3.txt
八、学习资源推荐
- 官方文档:
- 经典教程:
- 《awk 编程入门》(在线阅读)
- Awk 简明教程
- 练习平台:
- awk.fishshell.com:在线调试 awk 命令。
通过大量练习 awk
的模式匹配和数据处理逻辑,能显著提升文本处理效率。结合 sed
和 grep
形成“文本处理三剑客”,可应对绝大多数数据处理场景! 🚀