如何在文件的第 n 列和第一行添加字符串?

如何在文件的第 n 列和第一行添加字符串?

我有一个制表符分隔的file,看起来像:

$ cat file
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558474.1  1155234 1156286 polyketide      synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558475.1  1156298 1156807 12      carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558476.1  1156804 1157820 -3      oxidoreductase [Mycobacterium]

其中1155234115628611562981156807和后跟制表1156804 符 1157820(即文件中除第六(最后)列外没有空格)。我想0在第五列添加一个制表符,并将第一行第六列末尾的制表符替换为空格。输出如下所示:

GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558474.1  1155234 1156286 0       polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558475.1  1156298 1156807 12      carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558476.1  1156804 1157820 -3      oxidoreductase [Mycobacterium]

如何使用 awk 或 sed 来做到这一点?

答案1

看起来好像有六个制表符分隔的列,但是当第五列中的值丢失时,某些处理已将第六列的第一个单词留在第五列中。这可能是由于先前的处理步骤使用空格或一般空白作为分隔符而不是制表符。

现在您想要在第 5 列中插入一个零,并将该单词移动到第 6 列中的正确位置。

我假设该文件如下所示,其中每个都是制表符(这是文件上^I的输出):cat -t

GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558474.1^I1155234^I1156286^Ipolyketide^Isynthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558475.1^I1156298^I1156807^I12^Icarboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558476.1^I1156804^I1157820^I-3^Ioxidoreductase [Mycobacterium]

目前还不清楚是否有空列2。如果有,只需在我下面使用的列号上加一即可。

$ awk -F '\t' 'BEGIN { OFS=FS } $5 ~ /[[:alpha:]]/ { $6 = $5 " " $6; $5 = 0 } { print }' file
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558474.1  1155234 1156286 0       polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558475.1  1156298 1156807 12      carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558476.1  1156804 1157820 -3      oxidoreductase [Mycobacterium]

在这里,我用来awk检测第五列中的任何字母。如果有,则在第 5 列前面添加一个与第 6 列分隔的空格,并将第 5 列设置为零。然后输出所有行,无论是否修改过。

答案2

您的答案可能基本上符合您的要求,但可以改进。

  • 您希望在合理的范围内最小化(简单)命令的数量和管道的数量。拥有超过您需要的数量可能会效率低下。在五行或十行的文件上您不会注意到它,但是,当您处理一百万行的文件时,它会产生影响。

    您不需要运行两个sed命令(一个通过管道传输到另一个)。你可以做

    sed-e'(第一的s命令)'-e'(第二s命令)'
    或者
    sed'(第一的s命令); (第二s命令)'

  • 从示例输出看来,您希望该选项卡仅在第一行变成空格,因此您的s/\t/ /命令也应该带有前缀1
  • 的行为s/…/…/6g未定义。由于您希望s/\t/ /只执行一次(在第 6 个选项卡上),因此您应该说 just s/\t/ /6(不带g)。

所以你的命令可能是

sed '1s/\t/\t0\t/4; 1s/\t/ /6'文件

大括号让您可以将想要完成的命令组合在一起。所以你也可以说

sed '1{s/\t/\t0\t/4; s/\t/ /6}'文件

awk

您可以在 awk 中执行此操作,如下所示:

awk -F '\t' -v OFS='\t' 'NR==1 { $6 = $5 " " $6; $5 =“0”}
                { 打印 }
    '文件

答案3

splice您可以使用场景中的内置函数对数组进行切片和切块,如下所示:

$ perl -F\\t -pale '
  next unless $. == 1;
  splice @F, 4, 2, 0, join $", @F[-2,-1];
  $_ = join "\t", @F;
' input.file

答案4

尝试使用以下命令效果很好

awk 'NR==1 {$8=$7;$7=$6;$6=$5;$5=0}1' filename| sed -r "s/\s+/ /g"| sed "s/ /\t/g

输出

GCF_000014165.1_ASM1416v1.dist_nbr_anntn    WP_011558474.1  1155234 1156286 0   polyketide  synthase    [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn    WP_011558475.1  1156298 1156807 12  carboxyl    methyltransferase   [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn    WP_011558476.1  1156804 1157820 -3  oxidoreductase  [Mycobacterium]

相关内容