简介:
awk 是面向文本处理的脚本语言,擅长按字段处理表格型文本(默认以空白分隔)。适用于日志分析、列计算、报表生成与简单的字符串处理。 GNU awk(gawk)还支持扩展特性与函数库。

基本语法:

1
2
awk 'pattern { action }' file1 file2 ...
# 或者带 -F 指定分隔符:awk -F, '{print $1}' file.csv

模式(pattern)可以是正则表达式、条件表达式或 BEGIN/END 块。动作为一段用大括号括起来的语句序列。

常用内置变量:

  • FS : 输入字段分隔符(默认空白,可设为正则或字符)
  • OFS : 输出字段分隔符(默认空格)
  • RS : 输入记录分隔符(默认换行)
  • ORS : 输出记录分隔符(默认换行)
  • NF : 当前记录的字段个数
  • NR : 已读的记录数(跨文件累计)
  • FNR : 当前文件的记录数(每个文件从1开始)
  • FILENAME: 当前处理的文件名

常用选项:

  • -F sep : 指定输入字段分隔符
  • -v var=val : 在脚本外设置变量
  • -f scriptfile : 从文件读取 awk 脚本
  • –re-interval : 允许 {n,m} 之类的正则量词(部分 awk 已默认支持)

常见示例:

  • 打印第1列与第3列:

    1
    awk '{print $1, $3}' file
  • 以逗号分隔的 CSV 打印第2列:

    1
    awk -F',' '{print $2}' file.csv
  • 统计某列求和(第3列为数值):

    1
    awk '{sum += $3} END {print sum}' file
  • 按某列分组计数(类似 SQL: GROUP BY):

    1
    awk '{cnt[$1]++} END {for (k in cnt) print k, cnt[k]}' file
  • 打印包含模式且显示行号:

    1
    awk '/error/ {print FILENAME ":" NR ":" $0}' *.log
  • 过滤并格式化输出(printf 用法):

    1
    awk '{printf "%-20s %10d\n", $1, $2}' data.txt
  • 只处理第 2~4 字段(改变 NF 后可重建行):

    1
    awk '{for(i=2;i<=4;i++) printf "%s%s", $i, (i<4?OFS:ORS)}' file

字段与字符串函数(常用):

  • length(s) : 字符串长度(无参时为 $0 长度)
  • substr(s, i, n)
  • index(s, t)
  • split(s, arr, sep)
  • tolower(s), toupper(s)
  • sprintf(fmt, …)

数组与关联数组:
awk 的数组是关联数组(索引为字符串)。常用于聚合、去重与连接模拟哈希表:

1
awk '{a[$1] = a[$1] $2 ","} END {for (k in a) print k, a[k]}' file

BEGIN / END 块:

  • BEGIN 在读取任何输入前执行(初始化)
  • END 在所有输入处理完后执行(汇总输出)
    示例:
    1
    awk 'BEGIN {print "Start"; OFS=","} {print $1, $2} END {print "Done"}' file

处理 CSV、复杂分隔与引号:
awk 原生对带引号的复杂 CSV 支持有限。简单 CSV 可用 -F’,’,复杂 CSV 推荐用专门库或工具(Python、csvkit、mlr)。

常见实用模式集:

  • 去除空白行:awk ‘NF’
  • 统计文件行数:awk ‘END{print NR}’ file
  • 取出第 1 列唯一值:awk ‘{print $1}’ file | sort -u
  • 根据第2列排序并取 topN(结合 sort):
    awk ‘{print $2, $0}’ file | sort -nr | head

与其他工具结合:

  • 与 sed/grep 联动过滤后用 awk 聚合:
    grep ‘pattern’ file | awk ‘{…}’
  • 与 sort/uniq 配合实现复杂分组统计:
    awk ‘{print $1}’ file | sort | uniq -c | sort -nr

进阶与性能提示:

  • 对大文件,尽量减少外部命令调用,使用内建函数与数组。
  • 避免在循环中频繁执行子进程(如 system()),会显著慢。
  • 对大量 CSV/JSON 等结构化数据,可考虑使用专门工具(jq、mlr、Python 的 pandas)或 gawk 的扩展库。

小结示例集:

1
2
3
4
5
6
7
8
# 计算第3列的平均值
awk '{sum+=$3; n++} END{print sum/n}' data.txt

# 找出文件中出现次数最多的第1列值
awk '{cnt[$1]++} END {for(k in cnt) print cnt[k], k}' file | sort -nr | head

# 使用 -v 传参并指定分隔符
awk -F: -v user=root '$1==user {print $0}' /etc/passwd

参考与扩展:

  • 查看 man awk 或 man gawk
  • GNU awk (gawk) 文档提供更丰富的扩展函数与库