AWK 是一种强大的文本处理工具,广泛用于 Linux/Unix 系统中对文本文件或数据流进行操作。它能够基于条件筛选、统计字段、重新排列数据等。主要特点包括:
2. AWK 的基本语法
2.1 AWK 程序的结构
AWK 程序的结构:
awk 'pattern { action }' file
2.2 常用内置变量
变量 | 含义 |
NR | 当前处理的行号 |
FNR | 当前文件的行号(处理多个文件时的相对行号) |
NF | 当前行的字段数(列数) |
2 | 第 1 列、第 2 列的值 |
$NF | 当前行的最后一列值 |
FS | 输入字段分隔符(默认为空格) |
OFS | 输出字段分隔符(默认空格) |
RS | 输入记录分隔符(默认为换行符) |
ORS | 输出记录分隔符(默认为换行符) |
ARGIND | 当前处理的文件在命令行参数中的索引 |
ARGC | 命令行参数的数量 |
ENVIRON | 存储当前环境变量的关联数组 |
FILENAME | 当前正在处理的文件名 |
SUBSEP | 数组下标分隔符(默认为 \034 ) |
RSTART | match 函数匹配字符串的起始位置 |
RLENGTH | match 函数匹配字符串的长度 |
以下是 常用内置变量 的补充说明,以 Markdown 格式输出:
变量说明:
2.3 运行 AWK 程序
AWK 程序可以通过以下方式运行:
注意事项:
• 未指定文件时,AWK 从标准输入读取数据;
• 可同时处理多个文件;
2.4 基本输出
2.5 高级输出
printf 格式化输出
printf
可以格式化输出内容,例如:
awk '{ printf "Name: %s, Age: %d\n", $1, $2 }' file.txt
排序输出
结合 sort
命令对输出进行排序:
awk '{ print $1 }' file.txt | sort
2.6 选择/过滤行
按某列的值
按某几列值的计算结果
按字符串匹配
不同方式的组合
BEGIN 和 END
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
内置函数
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
3. 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 "\n" } | 无 |
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 } | 无 |
-
-
• 基于模式匹配: 根据条件筛选数据。
-
• 列操作能力: 简单高效地处理文本列数据。
-
• 轻量编程语言: 提供内置变量、循环、条件语句等编程功能。
-
相关资料
《AWK 编程语言》:
-
https://github.com/wuzhouhui/awk/blob/twoside/The_AWK_Programming_Language_zh_CN.pdf
-
• pattern: 指定操作的匹配规则,例如正则表达式、逻辑判断等。
-
• action: 指满足条件时要执行的操作,用
{}
包围,例如打印、统计、替换等。 -
• file: 要处理的文本文件名称。
-
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
-
-
RS 和 ORS 的高级用法:
-
• 可以修改
RS
和ORS
来处理非标准格式的文件。例如,将RS
设置为空字符串,以处理多行记录:awk 'BEGIN { RS = "" } { print $0 }' file.txt
-
-
SUBSEP 的高级用法:
-
• 可以修改
SUBSEP
来定义多维数组的下标分隔符。例如:awk 'BEGIN { SUBSEP = ":"; arr["a", "b"] = 10; print arr["a", "b"] }'
-
-
RSTART 和 RLENGTH 的高级用法:
-
• 结合
match
函数,可以提取匹配的子字符串。例如:awk 'BEGIN { str = "hello world"; match(str, /world/); print substr(str, RSTART, RLENGTH) }'
-
-
ENVIRON 的高级用法:
-
• 可以遍历
ENVIRON
数组,打印所有环境变量。例如:awk 'BEGIN { for (key in ENVIRON) print key, ENVIRON[key] }'
-
-
FILENAME 的高级用法:
-
• 在处理多个文件时,可以根据文件名执行不同的操作。例如:
awk '{ if (FILENAME == "file1.txt") print "File1:", $0; else print "File2:", $0 }' file1.txt file2.txt
-
-
命令行直接运行:
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 '{ print $0 }' file.txt
-
• 打印文件的第 1 列和第 3 列:
awk '{ print $1, $3 }' file.txt
-
• 打印第 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
块在处理输入后执行:awk 'BEGIN { print "Start" } { print } END { print "End" }' file.txt
-
• 统计行数、单词数、字符数:
awk '{ chars += length($0); words += NF } END { print "Lines:", NR, "Words:", words, "Chars:", chars }' file.txt
-