70134

351 分钟

#Bash 的 awk 命令

awk [OPTION]... PROGRAM FILE...

功能

对文件进行模式扫描和处理。

类型

可执行文件(/usr/bin/awk)。

通常是 GNU AWK 的符号链接:

$ ls -l /usr/bin/awk
lrwxrwxrwx 1 root root 21 Apr  8  2024 /usr/bin/awk -> /etc/alternatives/awk
$ ls -l /etc/alternatives/awk
lrwxrwxrwx 1 root root 13 Apr 23  2024 /etc/alternatives/awk -> /usr/bin/gawk

参数

  • OPTION 选项:
    • -f program-file, --file program-file - 从 program-file 文件中读取 AWK 程序;可以多次使用此选项传递多个 AWK 程序
    • -F fs, --field-separator fs - 使用 fs 作为输入字段的分隔符
    • -v var=val, --assign var=val - 预定义脚本中的变量
    • -b, --characters-as-bytes - 将所有输入数据视为单字节
    • -c, --traditional - 使用兼容模式(GNU awk 的行为将与 Brian Kernighan 的 awk 一致)
    • -C, --copyright - 打印版权信息
    • -d[file], --dump-variables[=file] - 导出全局变量
    • -D[file], --debug[=file] - 启动调试程序,从 file 文件中读取调试命令并执行
    • -e program-text, --source program-text - 通过字符串 program-text 指定 AWK 程序;可以多次使用此选项传递多个 AWK 程序
    • -E file, --exec file - 类似 -f 选项,总是最后处理此选项;主要用于 #!
    • -g, --gen-pot - 不执行 AWK 程序,而是生成 .pot 文件
    • -i include-file, --include include-file - 加载 AWK 库
    • -I, --trace - 程序运行时打印内部字节码
    • -l lib, --load lib - 从动态库加载 GNU AWK 扩展
    • -L [value], --lint[=value] - 对可疑或不可移植的 AWK 代码发出警告
    • -M, --bignum - 对数值进行无限精度运算
    • -n, --non-decimal-data - 解析输入数据时识别八进制和十六进制数值;谨慎使用
    • -N, --use-lc-numeric - 解析输入数据时使用本地化的小数点格式
    • -o[file], --pretty-print[=file] - 将程序的格式化输出版本保存到 file 文件(默认为 awkprof.out);使用此选项是默认关闭优化
    • -O, --optimize - 开启优化
    • -p[prof-file], --profile[=prof-file] - 开启性能分析,结果保存到 prof-file 文件(默认为 awkprof.out
    • -P, --posix - 使用 POSIX 兼容模式,关闭 GNU 扩展
    • -r, --re-interval - 启用正则表达式中的区间表达式
    • -s, --no-optimize - 关闭优化
    • -S, --sandbox - 在沙盒模式下运行
    • -t, --lint-old - 对无法移植到原始 UNIX awk 的代码发出警告
    • -h, --help - 显示帮助
    • -V, --version - 显示版本
  • PROGRAM - AWK 程序字符串
  • FILE - 输入文件,省略此参数或将此参数设为 - 则读取标准输入

#内置变量

变量含义说明
$0当前整行代表当前读入的完整一行文本。
$1 - $n第N个字段2 是第二列,以此类推。
NRNumber of Records当前处理的行号 (1, 2, 3...)。
NFNumber of Fields当前行拥有的列数 (字段总数)。
FSField Separator输入域(列)分隔符(默认是空格/Tab)。
OFSOutput Field Separator输出域(列)分隔符(默认是空格)。
RSRecord Separator输入记录(行)分隔符(默认是换行)。
ORSOutput Record Separator输出记录(行)分隔符(默认是换行)。

#脚本

AWK 脚本通常由三部分组成:

  1. BEGIN { ... }: 在读取任何文件内容之前执行一次(常用于初始化变量、打印表头)
  2. pattern { ... }: 对 pattern 匹配的每一行文本执行(处理主体)
  3. END { ... }: 在处理完所有行之后执行一次(常用于打印汇总结果)

例如:

$ awk 'BEGIN{ print "开始处理..." } { print $0 } END{ print "处理结束" }' filename

#示例

假设我们要处理一个名为 data.txt 的文件,内容如下:

Name    Dept    Salary
Alice   HR      5000
Bob     IT      8000
Charlie IT      8500
David   HR      5200

提取列

$ awk '{print $1, $3}' data.txt             # 打印第 1 列和第 3 列
Name Salary
Alice 5000
Bob 8000
Charlie 8500
David 5200

条件过滤

$ awk '$2 == "IT" {print $1, $3}' data.txt  # 第 2 列是 "IT" 时,打印第 1 列和第 3 列
Bob 8000
Charlie 8500
  • $2 == "IT"pattern,表示第 2 列等于 "IT" 的行

正则匹配

$ awk '$1 ~ /^D/ {print $0}' data.txt       # 当第 1 列正则匹配 ^D 时打印整行
David   HR      5200
  • $1 ~ /^D/pattern,表示第 1 列正则匹配 ^D 的行
  • ~ 表示正则匹配,!~ 表示正则不匹配

格式化输出

$ awk 'NR > 1 {printf "%-10s %-5s $%d\n", $1, $2, $3}' data.txt
Alice      HR    $5000
Bob        IT    $8000
Charlie    IT    $8500
David      HR    $5200
  • NR > 1pattern,表示行号大于 1 的行

高级技巧

$ awk 'BEGIN{OFS=","} NR>1 {$3 = $3 * 1.1; print $1, $2, $3}' data.txt
Alice,HR,5500
Bob,IT,8800
Charlie,IT,9350
David,HR,5720
  • 开始截断修改了变量 OFS,指定分隔符为逗号
  • $3 = $3 * 1.1 修改了第 3 列的值,使其增加了 10%

#推荐阅读

#手册

更新: 2026/2/6

作者: PlanC

创建: 2026/2/6