如何修改Ed Morton的AWK脚本以实现多列数据组内最大值行全列输出
按分组保留最大值行(含重复行)的AWK解决方案
本次需求为:处理包含多列的数据,按第一列分组,保留第二列值为组内最大值的所有行(包括重复最大值的行),并输出全部列。
示例数据与期望输出
示例数据:
a 130 data1 a 55 data2 a 66 data3 b 88 data4 b 99 data5 b 99 data6 c 110 data7 c 130 data8 c 130 data9
期望输出:
a 130 data1 b 99 data5 b 99 data6 c 130 data8 c 130 data9
已实现需求的AWK脚本
@jared_mamrot 提供的脚本
通过两次读取文件,第一次记录每组的最大值,第二次筛选出符合最大值的行,直接输出完整行内容:
awk 'NR==FNR{if($2 > max[$1]){max[$1]=$2}; next} max[$1] == $2' file file
@Andre Wildberg 提供的脚本
使用数组分别记录每组最大值、对应行的数量和完整行内容,最后遍历数组输出所有符合条件的行:
awk 'arr[$1] < $2{arr[$1] = $2} arr[$1] == $2{n[$1,arr[$1]]++; line[$1,arr[$1],n[$1,arr[$1]]] = $0} END{for(i in arr){ j=0; do{j++; print line[i,arr[i],j]} while(j < n[i,arr[i]])}}' file
修改Ed Morton的脚本以支持多列输出
原脚本仅能处理两列数据,仅输出键和值列:
sort file | awk ' { cnt[$1,$2]++; max[$1]=$2 } END { for (key in max) { val=max[key]; for (i=1; i<=cnt[key,val]; i++) print key, val } } '
要让它支持多列输出,需要调整数组存储逻辑,记录完整的行内容而非仅计数。以下是两种修改方案:
方案一:结合排序优化
先按第一列分组、第二列降序排序,再收集每组最大值对应的所有行:
sort -k1,1 -k2,2nr file | awk ' !max[$1] { max[$1] = $2 } $2 == max[$1] { lines[$1][++cnt[$1]] = $0 } END { for (key in lines) { for (i=1; i<=cnt[key]; i++) { print lines[key][i] } } } '
方案二:无需排序,两次读取文件
和@jared_mamrot的脚本逻辑一致,先获取每组最大值,再筛选输出完整行:
awk ' NR == FNR { if ($2 > max[$1]) max[$1] = $2; next } $2 == max[$1] { print $0 } ' file file
方案三:基于原脚本结构修改
保留原脚本的单次读取逻辑,调整数组存储完整行内容:
sort file | awk ' { if ($2 > max[$1]) { max[$1] = $2 delete lines[$1] cnt[$1] = 0 } if ($2 == max[$1]) { lines[$1][++cnt[$1]] = $0 } } END { for (key in lines) { for (i=1; i<=cnt[key]; i++) { print lines[key][i] } } } '
内容的提问来源于stack exchange,提问作者SWK
相关产品推荐
相关产品推荐

