首页/系统/Linux 运维命令速查/awk 双文件处理(NR==FNR)
文本处理77 条

awk 双文件处理(NR==FNR)

经典套路:先读小文件建索引/过滤集,再流式处理大文件——按列 join 不需要排序,比 join 命令更实用。

Linux 运维命令速查系统更新于 2026-10-13

awk 双文件是什么

awk 处理两个文件时有经典套路:利用 NR(累计行号)与 FNR(当前文件行号)在第一个文件里相等这一点,先把小文件读进数组建索引,再逐行处理大文件。这样就能做按列关联,而且输入不需要预先排序。

基本信息

用途两文件关联,用于过滤、映射与计数
语法awk 'NR==FNR{建索引; next} {处理}' 小文件 大文件
原理第一个文件里 NR 与 FNR 相等
优势无需排序,输出格式完全自由

典型使用场景

  • 白名单过滤:把允许清单读进内存,再筛大文件里的命中行
  • 按列映射:用小文件把代码翻译成名称,补充可读字段
  • 分组计数:统计每个用户或每个接口出现的次数
  • 字段合并:把两个来源的字段拼成一行输出
  • 替代 join:输入无需排序,也能自由控制输出格式

按列映射与过滤

按列映射与过滤
awk 'NR==FNR{a[$1]=$2; next} {print $1, a[$1]}' map.txt data.txt
awk 'NR==FNR{ok[$1]; next} ($1 in ok)' allow.txt access.log
awk -F: 'NR==FNR{name[$3]=$1; next} {print name[$1], $2}' /etc/passwd data.txt

分组计数与加权求和

分组计数与加权求和
awk 'NR==FNR{u[$1]; next} ($1 in u){n[$1]++} END{for(k in n) print k, n[k]}' users.txt logs.txt
awk 'NR==FNR{a[$1]=$2; next} {s+=$3*a[$1]} END{print s}' rate.txt usage.txt
awk 'NR==FNR{a[$1]=$2; next} {print $0, a[$1]}' OFS=, map.txt data.txt

关键变量

变量含义用法
NR累计已读行数跨文件累加
FNR当前文件内的行号每个文件重新计数
NR==FNR只在第一个文件成立用于建立索引
next跳过后续动作索引阶段读完即跳过
关联数组充当哈希表用字段做键存放映射
比 join 好用在于输入无需排序,比按模式匹配文件更强在于能带出关联字段或做累加。
字段分隔符用 -F 指定,输出分隔符用 -v OFS 指定,处理账号文件或 CSV 时先明确分隔符。
映射数组一对多时只保留最后一个值,会静默丢数据,需要全部值时改成拼接或直接计数。
参数顺序不能颠倒:索引必须来自小文件,把大文件放在前面会让关联数组占用大量内存。
计数结果统一在结束段输出,避免边处理边打印导致结果散落,也更便于排序与二次处理。

易错点

  • 映射赋值只保留最后一个值,一对多场景会静默丢数据,应改成拼接字符串或计数
  • 第二个文件的处理动作写空会什么都不输出,改完先在小样本上验证
  • 把大文件当作第一个参数传入会让索引数组占用大量内存,参数顺序不能颠倒
  • 字段分隔符没指定时按空白切分,含空格的字段会被切错列,先明确分隔符

数据来源与参考

  • man 1 awk(GNU gawk 手册)
  • gawk 官方用户指南(gnu.org/software/gawk/manual)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌