AWK多列条件遍历 满足条件输出首列值的实现方法
TSV按列归集筛选AWK方案
问题说明
待处理数据为制表符分隔(TSV)格式,实际数据量约20000行,示例数据如下:
Names USA EU FR Jim 3 12 5 John 8 4 7 Jane 12 35 3 Sue 6 3 9

处理规则
从第2列开始遍历所有列,收集单元格数值大于5对应的行首列(名称列)值,最终输出制表符分隔结果,要求:
- 首行为原数据第2列及之后所有列的表头
- 每列下方按顺序排列对应列满足数值>5条件的名称
预期输出:
USA EU FR John Jim John Jane Jane Sue Sue

原有脚本问题
之前编写的脚本:
awk -F"\t" '{ for(i=2; i<=NF; i++) { if($i > 5){ print $1 } } }' file > results
存在两个核心问题:
- 遍历到符合条件的值就直接打印名称,没有按列做归集存储,所有结果只能输出到单列,无法对齐成多列格式
- 未单独处理首行表头,后续尝试添加的
print FNR == i {print $1} "\n"不符合awk语法规则(不支持将条件代码块直接嵌套在print语句内),因此触发语法报错:
awk: cmd. line:4: print FNR == i {print $1} "\n" awk: cmd. line:4: ^ syntax error awk: cmd. line:8: } awk: cmd. line:8: ^ syntax error
正确实现脚本
BEGIN { FS = "\t" OFS = "\t" } NR == 1 { col_total = NF - 1 for (i=2; i<=NF; i++) { idx = i - 1 header[idx] = $i col_len[idx] = 0 } next } { for (i=2; i<=NF; i++) { if ($i + 0 > 5) { idx = i - 1 col_len[idx]++ res[idx, col_len[idx]] = $1 max_row = (col_len[idx] > max_row ? col_len[idx] : max_row) } } } END { # 打印表头 for (i=1; i<=col_total; i++) { printf "%s%s", header[i], (i==col_total ? "\n" : OFS) } # 逐行打印归集结果 for (r=1; r<=max_row; r++) { for (i=1; i<=col_total; i++) { val = (r <= col_len[i] ? res[i, r] : "") printf "%s%s", val, (i==col_total ? "\n" : OFS) } } }
使用方法
将脚本保存为filter.awk,执行命令:
awk -f filter.awk input.tsv > output.tsv
脚本单次遍历文件即可完成所有归集操作,处理20000行数据无性能压力,内存占用仅和符合条件的结果总量相关。
内容的提问来源于stack exchange,提问作者Haloor
相关产品推荐
相关产品推荐

