基于Awk实现记录重复统计与指定列极值提取需求求助
需求说明
- 以
substr($0,20,18)作为分组键,统计每组记录的重复次数,输出每组的最后一行,并在末尾追加重复次数 - 针对每组的第7列,找出最小值和最大值,分别放到输出行的第4、5列
输入输出示例
输入文件内容
M G 36829.00 37145.00 1 2161 36840.00 37146.00 37576
M G 36829.00 37145.00 217 4321 36852.00 37146.00 37576
M G 36829.00 37145.00 433 6481 36864.00 37146.00 37576
M G 36829.00 37145.00 649 8641 36876.00 37146.00 37576
M G 36829.00 37145.00 865 10801 36888.00 37146.00 37576
M G 36833.00 38033.00 1 4321 36840.00 37602.00 38464
M G 36833.00 38033.00 433 8641 36852.00 37602.00 38464
M G 36833.00 38033.00 865 12961 36864.00 37602.00 38464
M G 36833.00 38033.00 1297 17281 36876.00 37602.00 38464
M G 36833.00 38033.00 1729 21601 36888.00 37602.00 38464
M G 37265.00 38105.00 1 4321 36840.00 37674.00 38536
M G 37265.00 38105.00 433 8641 36852.00 37674.00 38536
M G 37265.00 38105.00 865 12961 36864.00 37674.00 38536
M G 37265.00 38105.00 1297 17281 36876.00 37674.00 38536
M G 37265.00 38105.00 1729 21601 36888.00 37674.00 38536
M G 37265.00 38105.00 2161 25921 36900.00 37674.00 38536
M G 37271.00 38885.00 1 2211 36840.00 38454.00 38894
M G 37271.00 38885.00 222 4421 36852.00 38454.00 38894
M G 37271.00 38885.00 443 6631 36864.00 38454.00 38894
M G 37271.00 38885.00 664 8841 36876.00 38454.00 38894
期望输出
36829.00 37145.00 10801 36840.00 36888.00 37146.00 37576 5
36833.00 38033.00 21601 36840.00 36888.00 37602.00 38464 5
37265.00 38105.00 25921 36840.00 36900.00 37674.00 38536 6
37271.00 38885.00 8841 36840.00 36876.00 38454.00 38894 4
现有代码问题分析
你之前的代码分成了两个独立的AWK命令,没办法把分组统计、最值提取和最后一行输出整合起来,而且处理第7列最值的逻辑过于繁琐,没必要拆分两次AWK处理。我们可以用一次AWK扫描完成所有需求,效率更高也更简洁。
完整解决方案
下面这个AWK脚本可以一次性完成所有要求:
{ key = substr($0, 20, 18) # 获取分组标识 count[key]++ # 累计每组记录数 last[key] = $0 # 保存每组最后一行内容 col7 = $7 + 0 # 把第7列转成数值,避免字符串比较误差 # 更新每组第7列的最小值和最大值 if (!(key in min7) || col7 < min7[key]) { min7[key] = col7 } if (!(key in max7) || col7 > max7[key]) { max7[key] = col7 } } END { # 遍历所有分组,按格式输出结果 for (k in count) { split(last[k], fields) # 拆分最后一行的字段 printf "%s %s %s %.2f %.2f %s %s %d\n", fields[3], fields[4], fields[6], min7[k], max7[k], fields[8], fields[9], count[k] } }
脚本说明
分组统计与记录保存:
- 用
key存储substr($0,20,18)的分组标识 count[key]++累计每组的记录数量last[key] = $0每次覆盖,最终保留每组的最后一行内容
- 用
最值计算:
col7 = $7 + 0把第7列的字符串转成数值,避免字符串比较的逻辑错误- 初始化或更新
min7[key]和max7[key],分别存储每组第7列的最小、最大值
结果输出:
- 遍历所有分组,用
split()把最后一行拆分成字段数组 - 按照期望格式重组输出:提取原行的第3、4、6、8、9字段,插入min和max作为第4、5列,最后追加统计次数
%.2f保证数值保留两位小数,和输入格式保持一致
- 遍历所有分组,用
使用方法
把上面的脚本保存为process.awk,然后执行:
awk -f process.awk input.txt > output.txt
这样就能得到你想要的输出结果啦!
内容的提问来源于stack exchange,提问作者OXXO

