awk 命令用法解析
一、概述
awk 是一款强大的文本处理与数据分析工具,尤其擅长对结构化文本(如日志、表格数据)进行查询、统计、替换、分析等操作。其核心特点是:
- 基于模式-动作对处理文本(匹配模式则执行动作)。
- 按行处理文本,自动将每行拆分为“字段”(默认以空格/制表符分隔),方便按列操作。
- 支持变量、函数、循环、判断等编程特性,可实现复杂逻辑。
二、基本语法
awk [参数] '模式 {动作}' [文件...]
核心参数
| 参数 | 作用 |
|---|---|
-F 分隔符 |
指定字段分隔符(默认:空格/制表符,支持正则,如 -F "[, :]+" 表示逗号、空格、冒号均为分隔符) |
-v 变量=值 |
定义内置变量(处理前初始化) |
-f 脚本文件 |
从文件中读取 awk 脚本(适用于复杂逻辑) |
核心概念
- 字段引用:
$0:表示整行内容。$n:表示第 n 列(如$1第一列,$3第三列)。$NF:表示最后一列(NF是内置变量,存储当前行的字段总数)。
- 模式:触发动作的条件,支持:
- 行号(
NR==3表示第三行)。 - 正则匹配(
/reboot/表示包含reboot的行)。 - 比较表达式(
$1~/^why/表示第一列以why开头)。
- 行号(
- 动作:对匹配行执行的操作,常用
print(打印)、gsub(替换)、变量运算等,需用{}包裹。
三、核心功能与示例
1. 基础查询(按行/列筛选)
(1)按行号查询
通过内置变量 NR(行号)指定目标行:
# 打印第1行和第3行
last | awk 'NR==1; NR==3'
# 打印1-3行
last | awk 'NR==1, NR==3'
(2)按内容匹配查询
通过正则表达式匹配包含特定内容的行:
# 打印包含"reboot"或"tty2"的行
last | awk '/reboot/; /tty2/'
# 打印第一列以"why"开头的行
last | awk '$1~/^why/'
(3)打印指定列
通过 $n 引用列,实现按列提取数据:
# 打印第1列和第3列(默认空格分隔列)
last | awk '/reboot/ {print $1, $3}'
# 打印最后一列($NF)
last | awk '/reboot/ {print $NF}'
# 自定义分隔符(以点分隔),打印IP地址的最后一段(第4列)
echo "192.168.0.102" | awk -F "." '{print $4}' # 输出:102
2. 文本替换
使用 gsub(原内容, 新内容, 列) 函数替换指定列的内容(支持正则),gsub 就是 gawk substitute:
# 将第三列中的点(.)替换为冒号(:)
last | awk '$1~/^why/ {gsub(/\./, ":", $3); print $3}'
# 示例输出:192:168:0:101
3. 数据统计与计算
(1)求和
通过变量累加实现数值求和:
# 计算1到10的总和(逐行打印累加结果)
seq 1 10 | awk '{sum = sum + $1; print sum}'
# 输出:
# 1
# 3(1+2)
# 6(1+2+3)
# ...
# 55(1到10总和)
(2)过滤与清洗
排除空行和注释行(以 # 开头):
# 过滤test03中既非空行也非注释行的内容
cat test03 | awk '!/^#|^$/' # !表示取反,^#表示以#开头,^$表示空行
4. 特殊模式(BEGIN/END)
BEGIN:处理文本前执行(常用于设置表头、初始化变量)。END:处理文本后执行(常用于汇总结果)。
# 打印表头,再输出last.txt的前3列(用column -t格式化对齐)
awk 'BEGIN{print "用户", "终端", "IP地址"}{print $1, $2, $3}' last.txt | column -t
# 统计文件总行数(END中打印NR的最终值)
cat test.txt | awk 'END{print "总行数:", NR}'
5. 多分隔符与复杂匹配
通过 -F 指定正则分隔符,处理多种分隔符混合的文本:
# 以制表符(\t)、空格、点(.)为分隔符,提取第6列
last.txt | awk -F "[\t .]+" '/why/ {print $6}'
四、常用示例汇总
| 需求 | 命令 |
|---|---|
| 打印文件第5行 | awk 'NR==5' file.txt |
| 打印所有行的第2列 | awk '{print $2}' file.txt |
| 以逗号分隔,打印第3列 | awk -F "," '{print $3}' data.csv |
| 统计包含"error"的行数 | awk '/error/ {count++} END{print count}' log.txt |
| 计算某列的平均值 | awk '{sum+=$3; count++} END{print sum/count}' data.txt |
五、注意事项
- 分隔符处理:连续空格会被视为单个分隔符(默认行为),需精确控制时用
-F显式指定。 - 变量作用域:
BEGIN中定义的变量可在整个处理过程中使用,NR(行号)、NF(字段数)为内置变量,自动更新。 - 正则转义:替换时特殊字符(如
.、*)需用\转义(如gsub(/\./, "-", $1))。 - 输出格式化:
print中用逗号分隔字段会自动添加空格,用printf可自定义格式(如printf "%.2f\n", $3)。
六、扩展:gawk
1. 定义与核心定位
gawk(GNU AWK)是 GNU 项目对 AWK 语言的实现,是 AWK 标准的超集。在绝大多数 Linux 系统中,awk 命令通常是 gawk 的符号链接(即 awk 实际调用的是 gawk)。
gawk 继承了传统 AWK 的所有功能(如按行/列处理文本、模式-动作机制),并扩展了更多特性(如增强的正则支持、更多内置函数、数组优化等),是处理结构化文本、日志分析、数据统计的强大工具。
2. 与传统 AWK 的核心差异
gawk 在兼容标准 AWK 的基础上,增加了多项实用扩展,主要差异如下:
| 特性 | 传统 AWK | gawk(GNU AWK) |
|---|---|---|
| 正则支持 | 基础正则(BRE)为主 | 支持扩展正则(ERE)及更多元字符(如 \y 单词边界) |
| 内置函数 | 基础字符串、数值函数 | 新增大量函数(时间处理、数组排序、高级字符串操作等) |
| 数组功能 | 仅支持一维关联数组 | 支持多维数组(模拟)、数组排序(asort/asorti) |
| 扩展语法 | 无特殊扩展 | 支持自定义函数、命名引用、BEGINFILE/ENDFILE 模式等 |
| 兼容性 | 严格遵循原始 AWK 标准 | 可通过 --posix 选项兼容 POSIX 标准,默认支持更多扩展 |
3. 核心扩展特性与示例
(1)增强的正则表达式支持
gawk 除支持标准 AWK 的正则语法外,还支持 GNU 扩展正则元字符,例如:
\y:匹配单词边界(如\yword\y匹配完整单词word)。\B:非单词边界。(?i):忽略大小写(仅在--re-interval选项开启时生效)。
# 匹配包含完整单词"boot"的行(不匹配"reboot"中的"boot")
gawk '/\yboot\y/' last.txt
(2)高级字符串处理函数
gawk 提供了比传统 AWK 更丰富的字符串函数,例如:
gensub(re, replacement, flags, target):支持捕获组引用(比gsub更灵活)。substr(s, i, n):提取子串(从位置i开始,长度n)。split(s, arr, sep):将字符串按分隔符拆分到数组。
# 使用 gensub 提取 IP 地址中的前两段(如"192.168")
echo "192.168.0.102" | gawk '{print gensub(/([0-9]+\.[0-9]+)\..+/, "\\1", "g", $0)}'
# 输出:192.168
(3)数组增强功能
gawk 对数组的支持更强大,包括:
- 多维数组(通过
arr[i,j]语法模拟,实际存储为i SUBSEP j)。 - 数组排序:
asort(arr)按值排序,asorti(arr)按键排序。
# 统计单词出现次数并按次数排序
echo "apple banana apple orange banana apple" | gawk '{
for(i=1;i<=NF;i++) count[$i]++ # 计数
}
END{
asorti(count, sorted) # 按单词(键)排序
for(i in sorted) print sorted[i], count[sorted[i]]
}'
# 输出:
# apple 3
# banana 2
# orange 1
(4)时间处理函数
gawk 提供了专门的时间处理函数,方便日志中的时间转换与计算:
mktime("YYYY MM DD HH MM SS"):将时间字符串转为时间戳(秒数)。strftime(format, timestamp):将时间戳转为指定格式的字符串。
# 将当前时间戳转为"年-月-日 时:分:秒"格式
gawk 'BEGIN{
ts = mktime("2023 11 16 18 30 00") # 时间戳
print strftime("%Y-%m-%d %H:%M:%S", ts)
}'
# 输出:2023-11-16 18:30:00
(5)自定义函数
gawk 支持用户自定义函数,可封装复杂逻辑,提高脚本复用性:
# 自定义函数计算平方和,并用其处理数据
gawk '
function sum_of_squares(a, b) { # 定义函数
return a*a + b*b
}
{
print "平方和:" sum_of_squares($1, $2) # 调用函数
}' data.txt
# 若 data.txt 内容为 "3 4\n5 12",输出:
# 平方和:25(3²+4²)
# 平方和:169(5²+12²)
(6)特殊模式:BEGINFILE/ENDFILE
gawk 新增 BEGINFILE(处理文件前执行)和 ENDFILE(处理文件后执行)模式,方便多文件处理时的初始化与收尾操作:
# 处理多个文件时,打印文件名及非空行数
gawk '
BEGINFILE {
print "=== 处理文件:" FILENAME " ===" # 文件名变量 FILENAME
count = 0 # 初始化计数器
}
NF > 0 { count++ } # 统计非空行
ENDFILE {
print "非空行数:" count "\n"
}
' file1.txt file2.txt
4. 常用参数
gawk 继承了 awk 的所有参数(如 -F 指定分隔符、-v 定义变量、-f 执行脚本文件),并新增部分扩展参数:
| 参数 | 作用 |
|---|---|
--posix |
启用 POSIX 兼容模式(禁用 GNU 扩展) |
--re-interval |
支持正则中的区间表达式(如 {n,m}) |
-W warning |
显示警告信息(如未使用的变量) |
-v VAR=VALUE |
定义全局变量(与标准 awk 一致) |