使用awk实现单列转未知数量多列 优化现有透视脚本的冗余空行问题
awk动态行转列效率优化方案
原有实现的核心缺陷
现有脚本采用三层嵌套循环,穷举c1、c2、c3三个字段所有去重值的全笛卡尔积,哪怕某组三字段组合完全没有关联的typ、val业务数据,也会强制生成输出行,最终产生大量无意义的空值记录。这种实现的运算量会随字段值数量呈指数级增长,在数据量较大时性能极差。
优化核心逻辑
彻底抛弃穷举全组合的思路,直接记录输入流中实际存在的c1/c2/c3三元组,仅对有效分组执行转列输出,从根源上消除无效运算:
- 遍历输入行时,自动收集所有出现的typ值,作为动态列的表头
- 每遇到新的c1/c2/c3三元组就登记一次,避免重复记录无效组合
- 维护分组与typ的对应值映射,供后续输出调用
优化后可直接落地的代码
awk -F'|' ' { # 去重收集所有typ值,生成动态列表头 current_typ = $4 if (! (current_typ in typ_tracker)) { typ_tracker[current_typ] = 1 typ_order[++typ_total] = current_typ } # 去重登记实际存在的c1/c2/c3分组 group_id = $1 FS $2 FS $3 if (! (group_id in group_tracker)) { group_tracker[group_id] = 1 group_order[++group_total] = group_id } # 存储分组下每个typ对应的val值 value_store[group_id, current_typ] = $5 } END { # 打印表头行 printf "c1|c2|c3" for (t_idx = 1; t_idx <= typ_total; t_idx++) { printf "|%s", typ_order[t_idx] } print "" # 逐个输出真实存在的分组数据 for (g_idx = 1; g_idx <= group_total; g_idx++) { current_group = group_order[g_idx] # 输出分组的c1/c2/c3基础值 printf "%s", current_group # 逐列对应每个typ,存在值就输出,不存在就留空 for (t_idx = 1; t_idx <= typ_total; t_idx++) { current_typ = typ_order[t_idx] current_val = value_store[current_group, current_typ] printf "|%s", current_val } print "" } }' 你的输入文件路径
实际输出验证
用需求中的测试输入运行,得到的结果和预期完全一致:
c1|c2|c3|AQ|MP|MX H2|f|1|2|1| H2|f|3|||1 H1|c|3||1|1
全程没有生成无业务数据的空行,且运算复杂度从原来的字段值笛卡尔积量级,降为实际存在的有效分组量级,数据量越大、无效组合越多的场景下,效率优势越明显。
内容的提问来源于stack exchange,提问作者M In
相关产品推荐
相关产品推荐

