复制第 1 行和第 2 行作为额外列

复制第 1 行和第 2 行作为额外列

我有一个 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==1as 条件。

  • NR==2{split($0, type, /#/)}:这将执行与上面解释的相同的操作,并存储在一个名为的数组中type,并且仅在具有 as 条件的第二条记录时运行NR==2

  • NR>2{ ... }:此代码块将针对其所在的记录/行运行数量记录数 >2

    • split($0, g, /#/):与第一项和第二项相同,并存储在名为 的数组中g
    • for (x in g) if(g[x]!="") print g[x], clstr[x], type[x]:现在我们循环遍历数组g索引的元素,如果它的值不为 null if(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

相关内容