如何用awk校验同程序不同bufferpool大小并输出全部异常记录
awk脚本排查程序大小不一致问题解答
最优实现方案
你提到的数组分组统计思路完全可行,是处理这类问题的最优解,不需要嵌套bash循环,纯awk即可实现,以下是两种场景的实现:
场景1:无需programs白名单,自动处理所有出现过的程序
创建脚本文件script.awk写入以下内容:
{ # 按程序名存储所有记录和对应大小 rec[$3][++cnt[$3]] = $1 " " $3 " " $2 size[$3][cnt[$3]] = $2 } END { # 遍历每个程序校验大小是否一致 for (prog in rec) { is_same = 1 base_size = size[prog][1] for (i = 2; i <= cnt[prog]; i++) { if (size[prog][i] != base_size) { is_same = 0 break } } # 大小不一致则输出该程序所有记录 if (!is_same) { for (i = 1; i <= cnt[prog]; i++) { print rec[prog][i] } } } }
执行命令:awk -f script.awk datafile
场景2:严格按照programs文件的白名单过滤程序
# 先读programs文件构建白名单 NR == FNR { allow[$1] = 1 next } # 仅处理白名单内的程序 allow[$3] { rec[$3][++cnt[$3]] = $1 " " $3 " " $2 size[$3][cnt[$3]] = $2 } END { for (prog in rec) { is_same = 1 base_size = size[prog][1] for (i = 2; i <= cnt[prog]; i++) { if (size[prog][i] != base_size) { is_same = 0 break } } if (!is_same) { for (i = 1; i <= cnt[prog]; i++) { print rec[prog][i] } } } }
执行命令:awk -f script.awk programs datafile
三个疑问解答
1. 如何获取缺失的那一行?
原逻辑仅在大小不一致时打印上一条记录的prev值,当前行的新大小没有被触发打印。比如处理到NATBPB对应的SPAP303行时,prev是之前的6286,和当前6700不等,你仅打印了上一条的6286记录,当前的6700记录没有输出,自然就缺失了。用数组存储所有记录后统一输出的方案可以完全避免漏行问题。
2. 为什么会出现奇怪的输出?
两个核心原因:
- 外层循环每遍历一个program就全量扫描一次datafile,所有行不管是不是当前目标程序都会被处理,非目标程序的行没有做跳过处理
- 第一次匹配到目标程序时,
prev变量还未赋值是空值,prev != $2条件会成立,就会打出后缀为空的异常行
另外你代码中else分支的print "ok"如果没有注释会输出大量ok,你看到的无ok结果大概率是后续过滤掉了ok行,但空值行和冗余行仍然保留了下来。
3. 数组存储后统一判断的思路是否可以实现?
完全可以,这是awk处理分组统计类问题的标准实现思路,上面给出的代码就是完全按照该逻辑编写的,运行效率远高于嵌套bash循环的写法,也不会出现漏行、冗余输出的问题。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

