我有一个包含不同列的文件(在这个简化的示例中为三列)。这些行包含不同复制的数据(Replicate_A、Replicate_B、Replicate_C)。但是,每个复制的行数并不相同(例如可以是 3、4、5 行)。我唯一知道的是每个重复都以数字 1 开头。我想添加一个带有重复名称的额外列。关于如何添加该列有什么建议吗?我可以创建一个额外的文件,其中包含要添加到该额外列中的名称列表。任何建议都有帮助。
我的文件是制表符分隔的文件。
1 x x
2 x x
3 x x
4 x x
1 x x
2 x x
3 x x
1 x x
2 x x
3 x x
我想要的文件
1 x x Replicate_A
2 x x Replicate_A
3 x x Replicate_A
4 x x Replicate_A
1 x x Replicate_B
2 x x Replicate_B
3 x x Replicate_B
1 x x Replicate_C
2 x x Replicate_C
3 x x Replicate_C
答案1
使用 AWK,并使用一个单独的文件列出要添加的名称:
#!/usr/bin/awk -f
BEGIN { FS = "\t"; OFS = FS; idx = 0 }
FNR == NR { names[NR] = $0 }
FNR < NR && $1 == 1 { idx++ }
FNR < NR { $(NF + 1) = names[idx]; print }
这将 AWK 设置为使用制表符作为输入和输出的字段分隔符。假定第一个文件包含要添加的名称;这被读入names
数组。一旦我们移动到第一个之后的文件,在检查第一个字段是否为 1 并增加数组索引(如果是)之后,我们将当前名称添加到行尾。
没有单独的姓名列表:
#!/usr/bin/awk -f
BEGIN { FS = "\t"; OFS = FS; idx = 0 }
$1 == 1 { idx++ }
{ $(NF + 1) = sprintf("Replicate_%c", 64 + idx); print }
在这两种情况下,都没有错误处理。在第一个变体中,一旦名称用完,将使用空字符串。在第二部分中,您将探索 Z 之后的角色集......
答案2
如果您可以使用数字而不是字母,则可以在 awk 中轻松执行此操作(file
具有在示例数据上运行的输出sed -i 's/ */\t/g'
,用制表符替换所有连续空格,因为您说数据是制表符分隔的):
$ awk -F"\t" -vOFS="\t" '{if($1==1){num++}{print $0,"Replicate_"num}}' file
1 x x Replicate_1
2 x x Replicate_1
3 x x Replicate_1
4 x x Replicate_1
1 x x Replicate_2
2 x x Replicate_2
3 x x Replicate_2
1 x x Replicate_3
2 x x Replicate_3
3 x x Replicate_3
如果你需要字母,那就有点复杂,但也不算太糟糕:
$ awk '{
if(NR==FNR){
a[++n]=$1
}
else{
if($1==1){
num++
}
print $0,"Replicate_"a[num]
}
}' <(printf '%s\n' {A..Z}) file
1 x x Replicate_A
2 x x Replicate_A
3 x x Replicate_A
4 x x Replicate_A
1 x x Replicate_B
2 x x Replicate_B
3 x x Replicate_B
1 x x Replicate_C
2 x x Replicate_C
3 x x Replicate_C