awk是Linux 文本处理的三驾马车之一.
awk 是一种强大的文本处理工具和编程语言,其名称取自三位创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 的姓氏首字母。它擅长处理结构化数据(如按行和列组织的文本),通常用于数据提取、报告生成和文本转换。
1. 基本语法
awk [选项] 'pattern { action }' 输入文件...
· pattern:匹配条件,决定何时执行后面的 action。如果省略,则对所有行执行 action。
· action:对匹配到的行执行的操作,用花括号 {} 包围。如果省略,则默认打印整行。
· 选项:常见的有 -F 指定字段分隔符,-v 定义变量等。
2. 工作原理
awk 逐行扫描输入文件(或标准输入),将每行按指定的分隔符(默认为空白字符)切割成多个字段,然后依次执行 pattern 匹配和 action 操作。处理完所有行后,可执行 END 块中的代码。
处理流程可以概括为:
1. 执行 BEGIN 块中的代码(仅在读取输入前执行一次)。
2. 从输入中读取一行。
3. 对该行执行所有匹配的 pattern { action }。
4. 重复步骤 2-3 直到文件结束。
5. 执行 END 块中的代码(仅在读取完所有输入后执行一次)。
3. 调用 awk 的方式
· 命令行直接运行
awk '/pattern/ {print $1}' file.txt
· 从文件读取脚本(适用于复杂脚本)
awk -f script.awk file.txt
· 可执行脚本
在脚本文件首行添加 #!/usr/bin/awk -f,然后赋予执行权限。
4. 模式和动作
· 模式(pattern) 可以是:
· 正则表达式:/regex/
· 关系表达式:$1 == "hello"
· 范围模式:NR==1, NR==5(从第 1 行到第 5 行)
· 特殊模式:BEGIN、END
· 模式组合:使用 &&(与)、||(或)、!(非)
· 动作(action) 是用 {} 括起来的语句序列,包含:
· 变量赋值
· 打印语句(print、printf)
· 控制语句(if、for、while 等)
· 数组操作
· 函数调用等
5. 内置变量
awk 提供了许多自动维护的变量:
变量 含义
FS 输入字段分隔符(默认空格或制表符)
OFS 输出字段分隔符(默认空格)
RS 输入记录分隔符(默认换行符)
ORS 输出记录分隔符(默认换行符)
NF 当前记录的字段数
NR 当前已处理的行数(从 1 开始)
FNR 当前文件中的行数(用于处理多个文件)
FILENAME 当前输入文件的文件名
$0 当前整行内容
$1, $2, ... 第 1、2... 个字段(字段编号从 1 开始)
示例:打印每行的行号和第一个字段
awk '{print NR, $1}' file.tx
6. 运算符
· 赋值:=, +=, -=, *=, /=, %=
· 比较:==, !=, <, <=, >, >=
· 匹配:~(匹配正则),!~(不匹配)
· 逻辑:&&, ||, !
· 算术:+, -, *, /, %
· 三元:条件 ? 表达式1 : 表达式2
· 连接:空格(用于字符串拼接)
7. 控制语句
· 条件判断
if (条件) {
语句块
} else if (条件) {
语句块
} else {
语句块
}
· 循环
while (条件) {
语句块
}
for (初始化; 条件; 更新) {
语句块
}
# 遍历数组
for (键 in 数组) {
语句块
}
· 跳出:break, continue, next(跳过当前行,开始下一行), exit(退出 awk
8. 数组
awk 支持关联数组(使用字符串作为下标)。
arr["key"] = value
delete arr["key"] # 删除元素
if ("key" in arr) # 检查元素是否存在
示例:统计文件中的单词出现次数
awk '{for(i=1;i<=NF;i++) count[$i]++} END {for(w in count) print w, count[w]}' file.txt
9. 内置函数
· 字符串函数:
length([s]) – 字符串长度
index(s, t) – 返回子串 t 在 s 中的位置(从 1 开始)
substr(s, i [, n]) – 返回 s 中从 i 开始的 n 个字符
split(s, a [, sep]) – 将字符串 s 按分隔符 sep 分割到数组 a
gsub(r, t [, s]) – 全局替换,返回替换次数
sub(r, t [, s]) – 第一次替换
match(s, r [, a]) – 正则匹配,返回位置
toupper(s) / tolower(s) – 大小写转换
· 数学函数:
sin(x), cos(x), sqrt(x), rand(), srand([x]), int(x) 等
· 时间函数(gawk 扩展):
systime() – 返回当前时间戳
strftime([format [, timestamp]]) – 格式化时间
10. 常用示例
a) 打印指定列
awk '{print $1, $3}' data.txt
b) 使用自定义分隔符
awk -F':' '{print $1}' /etc/passwd # 打印用户名
c) 条件过滤
awk '$3 > 50 {print $1, $3}' scores.txt # 打印第三列大于50的行
d) 使用 BEGIN 和 END
awk 'BEGIN {print "开始处理"} {print $0} END {print "处理完成"}' file.txt
e) 求和、平均值
awk '{sum += $1} END {print "总和:", sum, "平均值:", sum/NR}' numbers.txt
f) 格式化输出(printf)
awk '{printf "姓名:%-10s 年龄:%d\n", $1, $2}' students.txt
g) 多文件处理
awk 'FNR==1 {print "处理文件:" FILENAME} {print $0}' file1.txt file2.txt
h) 合并两个文件(类似 join)
假设 file1 包含 ID 和姓名,file2 包含 ID 和分数:
awk 'NR==FNR {a[$1]=$2; next} $1 in a {print $1, a[$1], $2}' file1 file2
i) 去除重复行(保留首次出现)
awk '!seen[$0]++' file.txt
11. 高级技巧
· 传递外部变量:使用 -v 选项
awk -v threshold=100 '$1 > threshold' data.txt
· 从 Shell 命令获取输入
awk '{print $1}' <(grep "error" log.txt)
· 生成随机数:rand() 和 srand()
· 使用自定义函数
function max(a, b) {
return a > b ? a : b
}
{ print max($1, $2) }
12. 总结
awk 是 Linux 文本处理的瑞士军刀,适合快速处理结构化数据。掌握它需要熟悉其数据模型(记录和字段)、内置变量、模式匹配以及编程结构。多练习常用场景(如日志分析、报表生成)是提高的关键。
对于更复杂的任务,可以结合 sed、grep、sort、uniq 等命令,形成强大的管道处理链。如果遇到性能瓶颈或需要更复杂的数据结构,可以考虑使用 Perl 或 Python,但 awk 的简洁性和效率在大多数情况下仍然是无与伦比的。