按固定首列分组转置聚合多数据集的awk实现(输出CSV格式)
适配需求的AWK处理实现
核心匹配逻辑
- 自动识别3个由空白行分隔的同结构数据块,无需手动标记块边界
- 匹配所有块内完全一致的首列标识序列(5.0到12.0、步长0.5),保证输入输出的标识顺序完全对齐
- 按原始5个数值列拆分独立输出分组,每组输出为4列CSV结构(1列标识值 + 3个块对应的同列数值),共生成5组结果,组间以空行分隔
可直接运行的AWK脚本
BEGIN { # 兼容任意空白分隔的列(空格、制表符均可识别) FS = "[[:space:]]+"; # 初始化块计数器与状态标记 block_id = 0; last_line_is_data = 0; # 匹配场景参数:3个独立数据块,单块每行附带5个数值列 total_value_cols = 5; } # 空白行处理 /^[[:space:]]*$/ { # 仅在有效数据行后遇到空行时才更新块计数,避免连续空行导致计数错误 if (last_line_is_data) { block_id++; last_line_is_data = 0; } next; } # 有效数据行处理 { # 第一个有效数据行出现时,初始化块序号 if (block_id == 0) block_id = 1; last_line_is_data = 1; # 取当前行首列的标识值 current_id = $1; # 仅在首次遇到标识时记录排列顺序,避免重复存储 if (!(current_id in id_seen)) { id_seen[current_id] = 1; id_order[++id_count] = current_id; } # 按 标识值、块序号、列序号 存储对应数值,为跨块聚合做准备 for (col = 1; col <= total_value_cols; col++) { data[current_id, block_id, col] = $(col + 1); } } END { # 逐列生成独立输出分组 for (out_col = 1; out_col <= total_value_cols; out_col++) { # 按原始标识顺序逐行输出 for (i = 1; i <= id_count; i++) { current_id = id_order[i]; # 输出标准CSV格式的4列内容:标识值 + 3个块的同列数值 printf("%s,%s,%s,%s\n", current_id, data[current_id, 1, out_col], data[current_id, 2, out_col], data[current_id, 3, out_col] ); } # 非最后一个分组时,输出空行分隔 if (out_col != total_value_cols) { print ""; } } }
实现特性
- 块计数逻辑加入了连续空行过滤,哪怕块之间间隔多段空白行,也能准确识别3个独立数据块,不会出现序号错位
- 跨块存储时以
标识值+块序号+列序号为键值,确保同标识、同列的数值能准确聚合,不会出现数据错配 - 输出时严格使用逗号分隔列,无冗余空格或特殊字符,符合标准CSV格式要求
运行方式
将脚本保存为col_agg.awk,在终端执行对应命令即可生成聚合结果:awk -f col_agg.awk 原始实验数据文件 > 聚合结果.csv
内容的提问来源于stack exchange,提问作者OXXO
相关产品推荐
相关产品推荐

