全文目录
- 1 工具介绍
- 2 核心优势
- 3 命令格式
- 3.1 命令格式说明
- 3.2 组成部分详解
- 3.2.1 选项
- 3.2.2 模式
- 3.2.3 动作
- 3.2.4 输入文件
- 4 使用说明
- 4.1 常用示例
- 4.2 awk 编程解析
- 4.2.1 基础说明
- 4.2.2 编程进阶
- 4.3 温馨提示
- 5 内置变量
- 6 参考文献
写在前面
前面一篇《Linux工作台文件操作命令全流程解析(高级篇之sed精讲)》精讲了文本流式处理工具 sed 。awk 前面也简单介绍过,但没有详细讲解过,所以本篇单独拿出来重点介绍下文本处理命令 awk ,这个命令是日常运维和处理分析日志的必备工具,掌握好它可以让我们的工作处理效率事半功倍。
1 工具介绍
awk 是一种强大的文本处理编程语言,诞生于1977年,由 Alfred Aho、Peter Weinberger 和 Brian Kernighan 三位贝尔实验室科学家联合开发(姓氏的首个字母,因此得名 AWK)。awk 逐行读入文件,以空格为默认分隔符,将每行切片,切开的部分再进行各种分析处理。awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 awk 的 GNU 版本。awk 拥有自己的语言,即 awk 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表等。所以, awk 不仅是命令行工具(awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本),更是结构化文本处理的终极解决方案,尤其擅长处理表格数据、生成统计报告和执行复杂数据转换。
2 核心优势
- 列式数据处理:自动分割每行数据为字段(列),默认以空格/tab为分隔符,可自定义
- 数学运算与统计计算
- 复杂条件过滤:多条件组合
- 数据格式化输出(printf)
- 关联数组与数据结构处理
3 命令格式
3.1 命令格式说明
# 基本命令格式
awk [选项] '模式 {动作}' 输入文件
# 使用脚本文件
awk -f 脚本文件 [选项] 输入文件
3.2 组成部分详解
3.2.1 选项
-F 分隔符:指定输入字段分隔符(如 -F’:’ 或 -F’\t’)
-v var=value:定义变量(如 -v name=John)
-f 脚本文件:从文件读取 AWK 程序
3.2.2 模式
正则匹配:/pattern/(如 /error/ 匹配包含 “error” 的行)
条件表达式:如 $3 > 25(第三列大于 25)
特殊模式:BEGIN(处理前执行)和 END(处理后执行)
逻辑组合:使用 &&(与)、||(或)连接多个条件(如 $2 == “Smith” && $3 < 30)
范围模式:模式1, 模式2(处理从匹配模式1到模式2之间的行)。
3.2.3 动作
作用域:用 {} 包裹,包含打印、计算、流程控制等语句
示例:{print $1, $3}(打印第一列和第三列)
多语句用 ; 分隔:{sum += $1; count++}
3.2.4 输入文件
多文件输入:可指定多个文件(如 file1.txt file2.txt)
不指定文件:若未指定,默认从标准输入读取
4 使用说明
4.1 常用示例
- 常规简单使用
# 打印第二列
awk '{print $2}' data.txt
# 指定分隔符(如逗号)
awk -F',' '{print $2}' data.txt
# 统计行数(含空行)
awk 'END {print NR}' data.txt
> 解释:NR(Number of Records)是 awk 的内置变量,表示已读取的总行数(包括所有输入文件)
# 统计非空行数量
awk 'NF > 0 {count++} END {print count}' data.txt
> 解释:NF 表示当前行的字段数,空行的 NF 为 0
# 统计空行数量
awk 'NF == 0 {count++} END {print count}' data.txt
# 统计包含特定内容的非空行(如第一列为 "Alice" 的行)
awk 'NF > 0 && $1 == "Alice" {count++} END {print count}' data.txt
# 统计行数并输出总行数与非空行数的比例
awk 'NF > 0 {non_empty++} {total++} END {printf "非空行比例: %.2f%%\n", (non_empty/total)*100}' data.txt
# 统计多个文件的非空行数并标记来源
awk 'NF > 0 {count[FILENAME]++} END {for(file in count) print file, count[file]}' file*.txt
# 条件过滤(第三列大于 25)
awk '$3 > 25 {print $0}' data.txt
# 变量传递
awk -v name="John" '$1 == name {print $3}' data.txt
# 计算和与均值
awk '{sum += $3} END {print "Sum:", sum, "Avg:", sum/NR}' data.txt
- BEGIN/END 块
# 以“:”为输入分隔符,“,”为输出分隔符,整理打印用户配置文件,输出用户名和用户ID所在的列内容
awk 'BEGIN {FS=":"; OFS=","} {print $1, $3} END {print "Done"}' /etc/passwd
命令格式:
awk 'BEGIN {初始化动作} 模式 {动作} END {结束动作}' 输入文件
- BEGIN 块:在处理输入文件前执行一次,用于初始化设置
- 中间的模式和动作:逐行处理输入文件时执行
- END 块:处理完所有输入行后执行一次
- BEGIN/END 块 - 拓展
# 添加条件过滤(例如仅输出用户 ID ≥ 1000 的用户)
awk 'BEGIN {FS=":"; OFS=","} $3 >= 1000 {print $1, $3} END {print "Done"}' /etc/passwd
# 输出到文件
awk 'BEGIN {FS=":"; OFS=","} {print $1, $3} END {print "Done"}' /etc/passwd > users.csv
# 添加表头
awk 'BEGIN {FS=":"; OFS=","; print "Username,UID"} {print $1, $3} END {print "Done"}' /etc/passwd
4.2 awk 编程解析
4.2.1 基础说明
- print和printf
awk中同时提供了print和printf两种打印输出的函数。print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。
- 变量和赋值
除了内置变量,awk也可以自定义变量。
# 统计/etc/passwd的账户人数
awk'{count++;print $0;} END{print "user count is ", count}' /etc/passwd # 无初始化
awk'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd # 初始化变量
> count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开
- 条件语句
awk中的条件语句是从C语言中借鉴来的,声明方式如下:
# if 语句
if (expression) {
statement;
statement;
... ...
}
# if|else 语句
if (expression) {
statement;
} else {
statement2;
}
# if|elseif|else 语句
if (expression) {
statement1;
} elseif (expression1) {
statement2;
} else {
statement3;
}
# 统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般是文件夹):
ls -l |awk'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
- 循环语句
awk中循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,关键字语义和C语言语义完全相同
- 数组
数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等
# 显示/etc/passwd的账户
awk -F ':''BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
4.2.2 编程进阶
- 字段处理黑科技
# 动态字段处理(修改第二列为哈希值)
awk '{
cmd = "echo " $2 " | sha256sum | cut -d\" \" -f1"
cmd | getline hash
close(cmd)
$2 = substr(hash,1,8)
}1' data.txt
# 字段重排(按指定顺序输出)
BEGIN { order[3]=1; order[1]=2; order[2]=3 }
{ for(i=1;i<=NF;i++) printf "%s:%s ", order[i], $i; print "" }
# 处理CSV(处理带逗号的字段)
awk -v FPAT='([^,]+)|("[^"]+")' '{print $3}' complex.csv
> FPAT(Field Pattern)是 GNU AWK 的扩展功能,允许通过正则表达式直接定义字段的匹配模式(而非传统分隔符 FS)。当字段包含特殊字符(如逗号)或被引号包裹时,FPAT 比 FS 更适合处理复杂结构
> 正则表达式 ([^,]+)|("[^"]+"):
> [^,]+:匹配一个或多个非逗号的字符(普通字段)。
> "[^"]+":匹配被双引号包裹的内容(字段内容可含逗号)。
> |:逻辑“或”操作,优先匹配左侧模式,若失败则尝试右侧模式。
- 结构化输出
# 格式化表格输出
awk 'BEGIN {printf "%-20s %10s\n","Name","Salary"}
{printf "%-20s %'10'd\n", $1, $2}' employees.txt
# 生成JSON数据
awk 'BEGIN {print "["}
NR>1 {printf " {\"id\":%d,\"name\":\"%s\"},\n", $1, $2}
END {print "{}]\n"}' data.txt
- 日志分析
# 统计Nginx访问日志
awk '{
status[$9]++
total++
if($9 >= 500) err500++
if($9 == 404) {not_found[$7]++}
}
END {
print "总请求:", total
print "状态码分布:"
for(s in status) print s, status[s]
print "\n500错误率:", err500/total*100 "%"
print "\n404高频资源:"
for(url in not_found) print url, not_found[url]
}' access.log
- 数据清洗
# 规范化电话号码格式
awk '{
gsub(/[^0-9]/, "", $3) # 去除非数字字符
if(length($3)==11)
$3 = substr($3,1,3)"-"substr($3,4,4)"-"substr($3,8)
print
}' contacts.txt
- 实时监控
# 实时内存警报
while true; do
free -m | awk '/Mem:/ {if($3/$2*100 > 90) system("echo 内存告警 | mail -s 'ALERT' admin@example.com")}'
sleep 60
done
4.3 温馨提示
- 引号规则:程序部分用单引号 ’ ’ 包裹,避免 Shell 解析特殊字符
- 字段处理:默认以空格/制表符分隔字段,连续空格视为单个分隔符
- 高级功能:支持数组、函数等(如 length($0) 计算行长度)
5 内置变量
变量 | 作用 | 默认值 |
---|---|---|
FS | 输入字段分隔符 | 空格/制表符 |
OFS | 输出字段分隔符 | 空格 |
RS | 输入记录分隔符 | \n |
ORS | 输出记录分隔符 | \n |
NR | 已读取的总行数 | - |
FNR | 当前文件已读取的行数 | - |
NF | 当前行的字段数 | - |
FILENAME | 当前处理的文件名 | - |
ARGC | 命令行参数个数 | - |
ARGV | 命令行参数数组 | - |
ENVIRON | 环境变量的关联数组 | 举例:awk 'BEGIN{print ENVIRON["PATH"]}' |
CONVFMT | 数字转换为字符串的格式 | %.6g |
OFMT | 数字输出的格式 | %.6g |
6 参考文献
文献1|文献2|文献3|文献4|GNU AWK手册
写在最后
文章由简入深介绍了 awk 文件处理工具,希望给读者有一个整体认知,用系统化的思路去认识 awk,希望可以帮助到读者。 如有任何问题,欢迎评论区指正与点评,同时,觉得对你有帮助,也欢迎点赞与收藏。我们共同努力,一起进步!