我有一个 file.txt (制表符分隔),其结构如下:
cluster01 cluster02 cluster03 ... cluster72
typeA_1 typeA_1 type2 ...
g1_A g4_D g8_H
g2_B g5_E g9_I
g3_C g6_F g10_J
g7_G g11_K
g12_L
该文件有 72 列,每列长度可变
我想将 file.txt 重新格式化为 newfile.txt 像
g1_A cluster01 typeA_1
g2_B cluster01 typeA_1
g3_C cluster01 typeA_1
g4_D cluster02 typeA_1
g5_E cluster02 typeA_1
g6_F cluster02 typeA_1
g7_G cluster02 typeA_1
g8_H cluster03 type2
g9_I cluster03 type2
g10_J cluster03 type2
g11_K cluster03 type2
g12_L cluster03 type2
答案1
另一个简单的awk
+sed
方法除了你有多少列之外,还有 3 行以上的缩进。
awk 'NR==1{split($0, clstr, /#/)} NR==2{split($0, type, /#/)}
NR>2 {split($0, g, /#/); for (x in g) if(g[x]!="") print g[x], clstr[x], type[x]
}' <(sed -E 's/\t/#/g' infile)
说明:
NR==1{split($0, clstr, /#/)}
: 我们用了awk split() 函数这划分了字符串/行/记录($0
在 awk 中指向整行细绳这里)分成由散列分隔的片段#
并存储在名为 的数组中clstr
,其中它的第一个记录仅具有NR==1
as 条件。NR==2{split($0, type, /#/)}
:这将执行与上面解释的相同的操作,并存储在一个名为的数组中type
,并且仅在具有 as 条件的第二条记录时运行NR==2
。NR>2{ ... }
:此代码块将针对其所在的记录/行运行氮数量右记录数 >2split($0, g, /#/)
:与第一项和第二项相同,并存储在名为 的数组中g
。for (x in g) if(g[x]!="") print g[x], clstr[x], type[x]
:现在我们循环遍历数组g
索引的元素,如果它的值不为 nullif(g[x]!="")
,则首先通过 打印它的值g[x]
,然后从clstr
数组中打印它的值,然后在type
数组中打印它的值。
请注意,在处理输入之前,我们将替换所有选项卡带有哈希字符
#
(您可以使用其他字符,但您应该确保文件中没有出现这种字符),然后将其传递给 awk。<(sed 's/\t/#/g' infile) ## or <(tr '\t' '#'< infile)
输入 (标签分隔):
cluster01 cluster02 cluster03 ... cluster72
typeA_1 typeA_1 type2 ...
g1_A g4_D g8_H
g2_B g5_E g9_I
g3_C g6_F g10_J
g7_G g11_K
g12_L
输出:
g1_A cluster01 typeA_1
g4_D cluster02 typeA_1
g8_H cluster03 type2
g2_B cluster01 typeA_1
g5_E cluster02 typeA_1
g9_I cluster03 type2
g3_C cluster01 typeA_1
g6_F cluster02 typeA_1
g10_J cluster03 type2
g7_G cluster02 typeA_1
g11_K cluster03 type2
g12_L cluster03 type2
答案2
Awk
固定解决方案“降序字段出现”从第 1 场到第 3 场:
awk 'NR == 1 {
group1 = $1; group2 = $2; group3 = $3
}
NR == 2 {
group1 = group1 OFS $1;
group2 = group2 OFS $2;
group3 = group3 OFS $3
}
NR > 2 {
if (NF == 3) { cl1[NR - 2] = $1 }
if (NF >= 2) { cl2[NR - 2] = $(NF - 1) }
cl3[NR - 2] = $(NF)
}
END {
traverse(cl1, group1);
traverse(cl2, group2);
traverse(cl3, group3)
}
function traverse(cl, gr) {
len = length(cl);
for (i = 1; i <= len; i++) {
print cl[i], gr
}
}' OFS='\t' file
输出:
g1 cluster01 typeA
g2 cluster01 typeA
g3 cluster01 typeA
g4 cluster02 typeA
g5 cluster02 typeA
g6 cluster02 typeA
g7 cluster02 typeA
g8 cluster03 typeB
g9 cluster03 typeB
g10 cluster03 typeB
g11 cluster03 typeB
g12 cluster03 typeB