Linux awk 命令
以下是关于 Linux 中 awk
命令的详细讲解,涵盖其基本概念、语法、内置变量、控制结构以及实际应用示例。
一、AWK 简介
AWK 是一种用于 模式扫描和处理 的文本处理工具,由 Aho、Weinberger 和 Kernighan 三位科学家共同开发(名字首字母缩写)。它特别适合处理 结构化文本数据(如日志、CSV 文件、配置文件等),支持字段操作、条件判断、数学运算、字符串处理等功能。
核心特点
- 逐行处理:按行读取输入数据,每行称为一条“记录”。
- 字段分割:默认以空格或制表符作为字段分隔符,可通过
-F
自定义分隔符。 - 模式匹配:基于正则表达式或条件筛选文本。
- 字段操作:轻松访问和操作文本中的字段(如
$1
表示第一个字段)。 - 算术与逻辑运算:支持加减乘除、条件判断等。
- 内置函数:提供字符串处理(如
length()
)、数学函数(如sqrt()
)等。 - 可移植性:适用于大多数类 Unix 系统。
二、基本语法
awk [选项] '模式 {动作}' 文件名
- 模式(Pattern):决定是否对某行执行动作(可选)。
- 动作(Action):对匹配行执行的操作(如打印、计算等)。
- 文件名:要处理的输入文件(可选,若未指定则从标准输入读取)。
常见选项
-F 分隔符
:指定字段分隔符(默认为空格)。-v var=value
:定义变量。-f 脚本文件
:从文件中读取 AWK 脚本。
三、工作原理
- 读取输入:逐行读取文件或输入流。
- 分割字段:根据分隔符将每行分割为字段(默认以空格/制表符分隔)。
- 匹配模式:检查当前行是否符合指定模式。
- 执行动作:对匹配行执行操作(如打印字段、计算值等)。
- 输出结果:将处理后的结果输出。
四、内置变量
变量名 | 说明 |
---|---|
$0 | 当前行的整行内容 |
$1, $2,... | 第1、第2…个字段(从1开始计数) |
NF | 当前行的字段总数 |
NR | 总行号(跨文件连续计数) |
FNR | 当前文件的行号(每个文件单独计数) |
FS | 输入字段分隔符(默认为空格) |
OFS | 输出字段分隔符(默认为空格) |
RS | 输入记录分隔符(默认为换行符) |
ORS | 输出记录分隔符(默认为换行符) |
FILENAME | 当前处理的文件名 |
示例
# 打印每行的字段数和整行内容
awk '{print NF, $0}' file.txt# 打印第三字段大于50的行
awk '$3 > 50 {print $1, $3}' file.txt
五、控制结构
1. 条件判断
# 判断字段值并输出
awk '{if ($1 == "root") print $2}' /etc/passwd
2. 循环
# 遍历字段
awk '{for(i=1; i<=NF; i++) print $i}' file.txt
3. 数组
# 统计字段出现次数
awk '{count[$1]++} END {for (key in count) print key, count[key]}' file.txt
4. 函数
# 自定义函数:计算平均值
awk '
function avg(total, count) {return total / count
}
{sum += $1; n++}
END {print "平均值:", avg(sum, n)}
' data.txt
六、内置函数
字符串处理函数
-
gsub(r, s [, t])
-
功能:全局替换字符串或正则表达式
r
为s
,作用范围默认是整个记录($0
),可指定目标字段t
。 -
示例:
awk '{gsub(/old/, "new", $1); print $0}' file.txt
-
sub(r, s [, t])
-
功能:替换第一个匹配的
r
为s
,作用范围同上。 -
示例:
awk '{sub(/old/, "new", $1); print $0}' file.txt
-
-
index(s, t)
-
功能:返回子串
t
在字符串s
中的首次出现位置(从 1 开始计数),未找到返回 0。 -
示例:
awk '{print index("hello world", "world")}' # 输出 7
-
-
split(s, a [, fs])
-
功能:按分隔符
fs
将字符串s
拆分成数组a
,返回拆分后的元素个数。 -
示例:
awk '{split("apple,banana,orange", arr, ","); for(i in arr) print arr[i]}'
-
-
substr(s, p [, n])
-
功能:从位置
p
开始截取字符串s
,长度为n
(可选),若未指定n
则截取到末尾。 -
示例:
awk '{print substr("hello", 2, 3)}' # 输出 "ell"
-
-
length([s])
-
功能:返回字符串
s
的长度(或当前记录$0
的长度)。 -
示例:
awk '{print length($0)}' file.txt # 输出每行的字符数
-
-
tolower(s)
/toupper(s)
-
功能:将字符串
s
转换为全小写/全大写。 -
示例:
awk '{print tolower("MiXeD cAsE")}' # 输出 "mixed case"
-
数学运算函数
-
int(expr)
-
功能:返回
expr
的整数部分(向下取整)。 -
示例:
awk 'BEGIN {print int(3.7)}' # 输出 3
-
-
sqrt(expr)
-
功能:返回
expr
的平方根。 -
示例:
awk 'BEGIN {print sqrt(16)}' # 输出 4
-
-
sin(x)
/cos(x)
/log(x)
/exp(x)
-
功能:三角函数和自然对数/指数运算(输入为弧度)。
-
示例:
awk 'BEGIN {print sin(3.14159265/2)}' # 输出 1.0
-
-
rand()
/srand([seed])
-
功能:生成
[0, 1)
区间的随机数,srand
可设置随机种子(默认使用时间戳)。 -
示例:
awk 'BEGIN {srand(); print int(100*rand())}' # 输出 0-99 的随机整数
-
数组与数据操作
-
asort(array, [sorted_array])
-
功能:对数组
array
进行排序,结果存储在sorted_array
(可选)。 -
示例:
awk 'BEGIN {arr[0]="banana"; arr[1]="apple"; asort(arr); for(i=1; i<=length(arr); i++) print arr[i]}'
-
-
split(s, a, fs)
- 功能:拆分字符串为数组(如上所述)。
-
match(s, r [, arr])
-
功能:检查字符串
s
是否匹配正则表达式r
,若匹配,返回起始位置,可将匹配结果存入数组arr
。 -
示例:
awk 'BEGIN {if (match("hello world", /world/)) print "Match found"}'
-
输入输出控制
-
close(file)
-
功能:关闭文件或管道。
-
示例:
awk '{print $0 > "output.txt"; close("output.txt")}'
-
-
fflush([file])
-
功能:刷新输出缓冲区(常用于实时输出)。
-
示例:
awk '{print $0; fflush()}'
-
-
system(command)
-
功能:执行系统命令。
-
示例:
awk '{system("date")}' # 每行输出当前时间
-
其他实用函数
-
sprint(fmt, expr1, expr2, ...)
-
功能:类似
printf
,但返回格式化后的字符串(不直接输出)。 -
示例:
awk 'BEGIN {str = sprintf("Value: %d", 42); print str}'
-
-
strtonum(str)
-
功能:将字符串转换为数值(支持八进制、十六进制)。
-
示例:
awk 'BEGIN {print strtonum("0x1F")}' # 输出 31
-
时间处理函数
-
systime()
-
功能:返回当前时间戳(秒数)。
-
示例:
awk 'BEGIN {print systime()}'
-
-
strftime([format, timestamp])
-
功能:格式化时间戳为可读字符串。
-
示例:
awk 'BEGIN {print strftime("%Y-%m-%d %H:%M:%S")}'
-
七、BEGIN 和 END 块
-
BEGIN
:在处理文本前执行(初始化操作)。 -
END
:在处理完所有行后执行(总结操作)。awk 'BEGIN { print "Start processing" } { sum += $1 } END { print "Total sum:", sum }' data.txt
八、高级功能
1. 模式匹配
- 正则表达式匹配:使用
/pattern/
匹配行。
# 打印包含 "error" 的行
awk '/error/' file.log
- 多模式匹配:
# 打印包含 "error" 或 "warning" 的行
awk '/error/, /warning/' file.log
2. 格式化输出
printf
:格式化输出(需手动添加换行符\n
)。
# 格式化输出行号和内容
awk '{printf "Line %d: %s\n", NR, $0}' file.txt
3. 处理多文件
# 同时处理多个文件并输出文件名
awk '{print FILENAME, $0}' file1.txt file2.txt
七、实际应用示例
1. 提取特定字段
# 提取 /etc/passwd 中用户名和用户ID
awk -F: '{print $1, $3}' /etc/passwd
2. 统计字段总和
# 提取特定字段或统计错误次数
awk '/ERROR/ { count++ } END { print "Total errors:", count }' access.log
3. 替换字段内容
# 将每行第二个字段替换为 "REPLACED"
awk '{$2 = "REPLACED"; print $0}' file.txt
4. 过滤特定行
# 打印包含 "success" 的行
awk '/success/ {print $0}' log.txt
5. 生成报表
# 生成学生平均成绩报告
awk '
{sum += $2; n++}
END {print "平均成绩:", sum/n}
' scores.txt
八、AWK 脚本编写
1. 编写脚本文件
创建 script.awk
文件:
{print $1, $NF
}
2. 执行脚本
awk -f script.awk file.txt
九、总结
- 适用场景:日志分析、数据统计、文本格式化、自动化脚本等。
- 优势:语法简洁,功能强大,适合处理结构化文本。
- 学习建议:结合
grep
、sed
、cut
等工具,掌握 AWK 的变量、数组、函数等进阶功能。
👍 逆风的方向,更适合飞翔
😊 希望对你有帮助!