Linux awk 命令使用说明
Linux awk 命令使用说明
简介
awk
是一种强大的文本处理工具,在 Linux/Unix 系统中被广泛使用。它由 Alfred Aho、Peter Weinberger 和 Brian Kernighan 开发,名称来源于他们姓氏的首字母。awk 能够对文本进行模式扫描、数据提取、统计分析和格式化输出等操作,特别适合处理结构化数据(如日志、CSV、表格等)。
基本语法
$ awk [选项] '模式 {动作}' 文件...
参数说明:
选项
:控制 awk 命令的行为模式
:用于匹配文本行的条件,可以是正则表达式、比较表达式等动作
:在匹配到的行上执行的操作,通常是一系列语句,用花括号{}
括起来文件
:要处理的文本文件,多个文件用空格分隔;若不指定文件,则从标准输入读取数据
常用选项
选项 | 描述 | 示例 |
---|---|---|
-F | 指定字段分隔符 | awk -F ',' '{print $1}' data.csv |
-f | 指定包含 awk 程序的文件 | awk -f script.awk data.txt |
-v | 定义变量并赋值 | awk -v var=10 '{print $1 + var}' data.txt |
-O | 优化输出,减少冗余空行 | awk -O '{print $1}' data.txt |
--posix | 启用 POSIX 兼容模式 | awk --posix '{print $1}' data.txt |
内置变量
变量 | 描述 | 示例 |
---|---|---|
$0 | 整行内容 | awk '{print $0}' data.txt |
$1, $2, ... | 第1、2、…个字段 | awk '{print $1, $3}' data.txt |
NF | 当前行的字段数量 | awk '{print NF}' data.txt |
NR | 当前行的行号 | awk '{print NR, $0}' data.txt |
FNR | 当前文件中的行号 | awk '{print FNR, $0}' file1.txt file2.txt |
FS | 字段分隔符(默认空格或制表符) | awk 'BEGIN{FS=","}{print $1}' data.csv |
OFS | 输出字段分隔符(默认空格) | `awk 'BEGIN{OFS=" |
RS | 记录分隔符(默认换行符) | awk 'BEGIN{RS=";"} {print $0}' data.txt |
ORS | 输出记录分隔符(默认换行符) | awk 'BEGIN{ORS=";"} {print $0}' data.txt |
FILENAME | 当前处理的文件名 | awk '{print FILENAME, $0}' data.txt |
模式匹配
1. 正则表达式模式
# 匹配包含 "error" 的行
$ awk '/error/ {print $0}' log.txt# 匹配以 "root" 开头的行
$ awk '/^root/ {print $0}' /etc/passwd# 匹配以 ".txt" 结尾的行
$ awk '/\.txt$/ {print $0}' file.list
2. 比较表达式模式
# 第二个字段大于 20 的行
$ awk '$2 > 20 {print $1}' students.txt# 第一个字段等于 "Bob" 的行
$ awk '$1 == "Bob" {print $0}' students.txt# 第三个字段不等于 "Math" 的行
$ awk '$3 != "Math" {print $1}' students.txt
3. 范围模式
# 匹配从包含 "start" 的行到包含 "end" 的行
$ awk '/start/,/end/ {print $0}' data.txt
动作语句
1. 输出语句
# 打印整行
$ awk '{print}' data.txt# 打印指定字段
$ awk '{print $1, $3}' data.txt# 格式化输出
$ awk '{printf "Name: %s, Age: %d\n", $1, $2}' students.txt
2. 条件语句
# 简单条件判断
$ awk '{if ($2 > 20) print $1 " is old"; else print $1 " is young"}' students.txt# 多条件判断
$ awk '{if ($2 > 20 && $3 == "CS") print $1}' students.txt
3. 循环语句
# for 循环
$ awk '{for (i=1; i<=NF; i++) print "Field " i ": " $i}' data.txt# while 循环
$ awk '{i=1; while (i<=NF) {print $i; i++}}' data.txt
使用示例
1. 基本数据提取
# 假设 students.txt 内容: Alice 20 CS Bob 22 Math Charlie 21 Physics# 打印所有行
$ awk '{print}' students.txt# 打印第一列
$ awk '{print $1}' students.txt# 打印第一列和第三列
$ awk '{print $1, $3}' students.txt# 指定分隔符为逗号
$ echo "Alice,20,CS" | awk -F ',' '{print $1, $3}'
2. 统计分析
# 统计文件行数
$ awk 'END{print NR}' data.txt# 统计字段数大于 3 的行数
$ awk 'NF > 3 {count++} END{print count}' data.txt# 计算第二列的总和
$ awk '{sum += $2} END{print sum}' numbers.txt# 统计每种 HTTP 方法的出现次数
$ awk '{method[$4]++} END{for(type in method) print type, method[type]}' server.log
3. 格式化输出
# 格式化打印表格
$ awk 'BEGIN{print "Name\tAge\tMajor"} {printf "%-10s %-5d %-10s\n", $1, $2, $3}' students.txt# 将输出字段分隔符设置为逗号
$ awk 'BEGIN{OFS=","} {print $1, $2, $3}' students.txt > students.csv
4. 文本处理
# 替换文本中的字符串
$ awk '{gsub(/error/, "warning"); print}' log.txt# 将第一列转换为大写
$ awk '{print toupper($1)}' data.txt# 提取文件中的 IP 地址
$ awk '{match($0, /([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/, ip); print ip[1]}' log.txt
5. 高级应用:BEGIN 和 END 块
# 在处理数据前输出表头
$ awk 'BEGIN{print "Name\tAge\tMajor"} {print $1, $2, $3}' students.txt# 在处理完所有数据后输出统计信息
$ awk '{sum += $2} END{print "Average age: " sum/NR}' students.txt# 结合 BEGIN 和 END 块
$ awk 'BEGIN{print "Start processing..."} $2 > 20 {count++} END{print "Total students over 20: " count}' students.txt
高级功能
1. 数组
# 关联数组示例
$ awk '{names[$1] = $2} END{print names["Bob"]}' students.txt# 数组遍历
$ awk '{count[$3]++} END{for(major in count) print major, count[major]}' students.txt
2. 函数
# 内置函数
$ awk '{print length($1)}' data.txt # 计算字符串长度
$ awk '{print substr($1, 1, 3)}' data.txt # 截取子字符串# 自定义函数
$ awk 'function max(a, b) {return a > b ? a : b} {print max($1, $2)}' numbers.txt
注意事项
- awk 中的变量不需要声明,直接使用即可
- 字符串连接使用空格,如
$1 " is " $2
- 正则表达式需用
/
包围 - 条件判断和循环语句需要用
{}
括起来 - BEGIN 块在处理输入前执行,END 块在处理完所有输入后执行
- 多个 awk 命令可以用
;
分隔 - 在命令行中使用 awk 时,注意引号的使用,避免与 shell 解析冲突
总结
awk
是 Linux 系统中功能强大的文本处理工具,通过模式匹配和动作执行,可以实现复杂的文本处理任务。掌握 awk 的使用,对于数据处理、日志分析和脚本编写都非常有帮助。