如何用Bash awk按匹配字符串拆分单列数据为多列?
解决单列数据按标记拆分多列的问题
我来帮你搞定这个需求!你遇到的核心问题是不同组行数不一致时列对齐错误,本质是之前的脚本没有正确跟踪每个组的行数据,也没处理行数差异的情况。下面给你一个能完美解决问题的awk脚本,附带详细解释和测试示例。
核心思路
我们需要用二维数组存储每个组(列)的每一行数据,同时记录所有组的最大行数,最后按行遍历输出每一列的对应内容——没有数据的位置自动留空,保证列对齐。
最终awk脚本
BEGIN { FS=OFS="\t" } /male_position/ { col++ row[col] = 0 next } { row[col]++ data[col, row[col]] = $0 if (row[col] > max_rows) max_rows = row[col] } END { for (r=1; r<=max_rows; r++) { line = "" for (c=1; c<=col; c++) { line = line (line ? OFS : "") data[c, r] } print line } }
脚本逐行解释
- BEGIN块:设置输入(
FS)和输出(OFS)分隔符为制表符,确保列用制表符分隔,和你的需求匹配。 - 匹配'male_position'时:
- 列计数器
col加1,代表新的一列开始。 - 初始化该列的行索引
row[col]为0,准备接收后续数据。 next跳过当前行,因为这个标记只是列的起始,不需要作为数据内容。
- 列计数器
- 处理普通数据行:
- 当前列的行索引
row[col]加1,记录这是该列的第N行。 - 把当前行内容存入二维数组
data[col, row[col]],相当于把数据放到「第col列第row行」的位置。 - 更新全局最大行数
max_rows,确保最后输出时能覆盖所有组的行。
- 当前列的行索引
- END块:
- 按行从1到
max_rows遍历,每一行对应输出结果的一行。 - 遍历每一列,取出对应位置的
data[c, r]拼接成一行——如果某列在该行没有数据,数组元素为空字符串,自然会留出空白位置,保证列对齐。
- 按行从1到
测试示例
假设你的test.file2内容如下:
male_position
a1
a2
male_position
b1
b2
b3
male_position
c1
运行脚本后,输出会是:
a1 b1 c1 a2 b2 b3
完全符合列对齐的要求,即使各组行数差异很大也不会错位。
内容的提问来源于stack exchange,提问作者user95146
相关产品推荐
相关产品推荐

