Linux AWK 指令指南 (awk command cheatsheet)
By Long Luo
AWK 是一种强大的文本处理工具,广泛用于 Linux/Unix 系统中对文本文件或数据流进行操作。它能够基于条件筛选、统计字段、重新排列数据等。主要特点包括:
- 基于模式匹配: 根据条件筛选数据。
- 列操作能力: 简单高效地处理文本列数据。
- 轻量编程语言: 提供内置变量、循环、条件语句等编程功能。
AWK 程序的结构
AWK 程序的结构:1
awk 'pattern { action }' file
- pattern: 指定操作的匹配规则,例如正则表达式、逻辑判断等。
- action: 指满足条件时要执行的操作,用 {} 包围,例如打印、统计、替换等。
- file: 要处理的文本文件名称
常用内置变量
变量 含义 NR 当前处理的行号 FNR 当前文件的行号(处理多个文件时的相对行号) NF 当前行的字段数(列数) 2 第 1 列、第 2 列的值 $NF 当前行的最后一列值 FS 输入字段分隔符(默认为空格) OFS 输出字段分隔符(默认空格) RS 输入记录分隔符(默认为换行符) ORS 输出记录分隔符(默认为换行符) ARGIND 当前处理的文件在命令行参数中的索引 ARGC 命令行参数的数量 ENVIRON 存储当前环境变量的关联数组 FILENAME 当前正在处理的文件名 SUBSEP 数组下标分隔符(默认为 \034) RSTART match 函数匹配字符串的起始位置 RLENGTH match 函数匹配字符串的长度 以下是 常用内置变量 的补充说明,以 Markdown 格式输出:
变量说明:
- NR 和 FNR 的区别:
• NR:累计行号,处理多个文件时行号会累加。 • FNR:当前文件的行号,处理多个文件时每个文件的行号从 1 开始重新计数。
- FS 和 OFS 的作用:
• FS:指定输入字段的分隔符,默认是空格。 • OFS:指定输出字段的分隔符,默认是空格。
- RS 和 ORS 的作用:
• RS:指定输入记录的分隔符,默认是换行符。 • ORS:指定输出记录的分隔符,默认是换行符。
- ENVIRON 的使用:
• ENVIRON 是一个关联数组,用于访问环境变量。例如:
awk ‘BEGIN { print ENVIRON[“HOME”] }’
- RSTART 和 RLENGTH: • 这两个变量与 match 函数配合使用,用于获取匹配字符串的起始位置和长度。例如:
awk ‘BEGIN { str = “hello world”; match(str, /world/); print RSTART, RLENGTH }’
- SUBSEP:
• 用于多维数组的下标分隔符,默认是 \034(非打印字符)。例如:
awk ‘BEGIN { arr[“a”, “b”] = 10; print arr[“a”, “b”] }’
- ARGIND 和 ARGC:
• ARGIND:当前处理的文件在命令行参数中的索引(从 1 开始)。 • ARGC:命令行参数的数量。例如:
awk ‘BEGIN { print ARGIND, ARGC }’ file1.txt file2.txt
- FILENAME: • 当前正在处理的文件名。例如:
awk ‘{ print FILENAME, $0 }’ file1.txt file2.txt
- 2, …, $NF:
• $1 表示第 1 列,$2 表示第 2 列,依此类推。
• $NF 表示当前行的最后一列。
- NF:
• 当前行的字段数(列数)。例如:
awk ‘{ print NF }’ file.txt 11. RS 和 ORS 的高级用法:
• 可以修改 RS 和 ORS 来处理非标准格式的文件。例如,将 RS 设置为空字符串,以处理多行记录:
awk ‘BEGIN { RS = “” } { print $0 }’ file.txt 12. SUBSEP 的高级用法:
• 可以修改 SUBSEP 来定义多维数组的下标分隔符。例如:
awk ‘BEGIN { SUBSEP = “:”; arr[“a”, “b”] = 10; print arr[“a”, “b”] }’ 13. RSTART 和 RLENGTH 的高级用法:
• 结合 match 函数,可以提取匹配的子字符串。例如:
awk ‘BEGIN { str = “hello world”; match(str, /world/); print substr(str, RSTART, RLENGTH) }’ 14. ENVIRON 的高级用法:
• 可以遍历 ENVIRON 数组,打印所有环境变量。例如:
awk ‘BEGIN { for (key in ENVIRON) print key, ENVIRON[key] }’ 15. FILENAME 的高级用法:
• 在处理多个文件时,可以根据文件名执行不同的操作。例如:
awk ‘{ if (FILENAME == “file1.txt”) print “File1:”, $0; else print “File2:”, $0 }’ file1.txt file2.txt 2.3 运行 AWK 程序 AWK 程序可以通过以下方式运行:
- 命令行直接运行:
awk ‘pattern { action }’ file • pattern:匹配条件(可选)。
• action:满足条件时执行的操作。
• file:要处理的文件。
- 脚本文件运行:
awk -f script.awk file 示例:假设 script.awk 内容如下:
{ print $1 } 运行命令:
awk -f script.awk file.txt • script.awk:包含 AWK 程序的脚本文件。
• file:要处理的文件。
注意事项:
• 未指定文件时,AWK 从标准输入读取数据;
• 可同时处理多个文件;
2.4 基本输出 • 打印文件的所有内容:
awk ‘{ print $0 }’ file.txt • 打印文件的第 1 列和第 3 列:
awk ‘{ print $1, $3 }’ file.txt 2.5 高级输出 printf 格式化输出 printf 可以格式化输出内容,例如:
awk ‘{ printf “Name: %s, Age: %d”, $1, $2 }’ file.txt 排序输出 结合 sort 命令对输出进行排序:
awk ‘{ print $1 }’ file.txt | sort 2.6 选择/过滤行 按某列的值 • 打印第 2 列大于 50 的行:
awk ‘$2 > 50 { print }’ file.txt 按某几列值的计算结果 • 打印第 1 列和第 2 列之和大于 100 的行:
awk ‘$1 + $2 > 100 { print }’ file.txt 按字符串匹配 • 打印包含 “error” 的行:
awk ‘/error/ { print }’ file.txt 不同方式的组合 • 打印第 2 列大于 50 且包含 “error” 的行:
awk ‘$2 > 50 && /error/ { print }’ file.txt BEGIN 和 END • BEGIN 块在处理输入前执行,END 块在处理输入后执行:
awk ‘BEGIN { print “Start” } { print } END { print “End” }’ file.txt 2.7 计算 统计数量:工时超过 15 小时的员工人数 awk ‘$3 > 15 { count++ } END { print count }’ file.txt 求和、求平均:平均工资 awk ‘{ sum += $2 } END { print “Average:”, sum/NR }’ file.txt 处理文本:打印时薪最高的员工信息 awk ‘$4 > max { max = $4; line = $0 } END { print line }’ file.txt 字符串拼接(concatenation):在一行内打印所有员工名 awk ‘{ names = names $1 ” ” } END { print names }’ file.txt 打印最后一行 awk ‘{ last = $0 } END { print last }’ file.txt 内置函数 • 统计行数、单词数、字符数:
awk ‘{ chars += length($0); words += NF } END { print “Lines:”, NR, “Words:”, words, “Chars:”, chars }’ file.txt 2.8 控制流 If-Else awk ‘{ if ($1 > 50) print “High”; else print “Low” }’ file.txt While awk ‘{ i = 1; while (i <= NF) { print $i; i++ } }’ file.txt For awk ‘{ for (i = 1; i <= NF; i++) print $i }’ file.txt 2.9 数组 统计每列的总和: awk ‘{ for (i = 1; i <= NF; i++) sum[i] += $i } END { for (i in sum) print “Column”, i, “Sum:”, sum[i] }’ file.txt
- AWK 示例速查表 以下是常见 AWK 功能及其对应程序和类似命令:
编号 功能 AWK 程序 类似命令 1 打印总行数 END { print NR } wc -l 2 打印第 10 行 NR == 10 { print } sed -n ‘10p’ 3 打印最后一列 { print $NF } 无 4 打印最后一行的最后一列 { f = $NF } END { print f } tail -n1 5 打印有 4 列以上的行 NF > 4 { print } 无 6 打印最后一列的值大于 4 的行 $NF > 4 { print } 无 7 打印所有输入的总字段数 { nf += NF } END { print nf } 无 8 打印包含关键字的总行数 /keyword/ { n++ } END { print n } grep -c ‘keyword’ 9 打印第 1 列的最大值及对应的行 $1 > max { max = $1; line = $0 } END { print max, line } 无 10 打印列数大于 1 的行 NF > 1 { print } 无 11 打印长度大于 80 的行 length($0) > 80 { print } 无 12 打印每行的列数和该行内容 { print NF, $0 } 无 13 打印第 2 列和第 1 列 { print $2, $1 } 无 14 交换第 1 列和第 2 列 { t = $1; $1 = $2; $2 = t; print } 无 15 第 1 列替换为行号 { $1 = NR; print } 无 16 删除第 2 列并打印 { $2 = ““; print } 无 17 倒序打印每行的字段 { for (i=NF; i>0; i–) printf”%s “, $i; printf”” } 无 18 计算每行的字段和 { sum=0; for (i=1; i<=NF; i++) sum += $i; print sum } 无 19 计算所有字段的总和 { for (i=1; i<=NF; i++) sum += \(i } END { print sum } 无 20 将所有字段取绝对值并打印 { for (i=1; i<=NF; i++) if (\)i<0) \(i = -\)i; print } 无