使用join

使用join

SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab SRR3384744.Gene.out.tabこの順序で複数のファイルとより多くのファイルがあります。このファイルから最初と4番目の列を抽出して出力ファイルに保存します。私のスクリプトが新しいファイルを読み取るときに、各ファイルの最後にデータを追加するのではなく、タブで区切られた方法でデータを抽出する必要があることを確認したいと思います。

入力ファイル:

SRR3384742.Gene.out.tab

N_unmapped      313860  313860  313860
N_multimapping  5786679 5786679 5786679
N_noFeature     286816  31696770        438410
N_ambiguous     1283487 32117   65902
AT1G01010       301     0       301
AT1G01020       623     1       622
AT1G03987       5       5       0
AT1G01030       151     2       149

SRR3384743.Gene.out.tab

N_unmapped      780346  780346  780346
N_multimapping  4621162 4621162 4621162
N_noFeature     182428  28470016        362650
N_ambiguous     1451612 43059   117293
AT1G01010       154     3       151
AT1G01020       685     2       683
AT1G03987       0       0       0
AT1G01030       63      0       63

私が得た結果は次のとおりです。

SRR3384742.Gene.out.tab 
AT1G01010       301
AT1G01020       622
AT1G03987       0
AT1G01030       149
SRR3384743.Gene.out.tab 
AT1G01010       151
AT1G01020       683
AT1G03987       0
AT1G01030       63

希望の出力:

SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab 
AT1G01010       301     151
AT1G01020       622     683
AT1G03987       0       0
AT1G01030       149     63

次のスクリプトを試しました。

for sample in *Gene.out.tab; do echo -en $sample "\n"; awk 'NR>4 {print $1 "\t" $4}' $sample; awk '{print $0, $sample}' OFS='\t' $sample; done > output

答え1

これにより、GNUを使用してコメントに記載されている出力が提供されますawk

gawk 'FNR==1{names[c++]=FILENAME}
      FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; } 
      END{ 
            for(i=0;i<=c;i++){
                printf "\t%s",names[i]
            } 
            printf "\n"; 
            for(i in lines){ 
                print i,lines[i]
            }
        }' *Gene.out.tab
    SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
AT1G01010   301 151
AT1G01020   622 683
AT1G01030   149 63
AT1G03987   0   0

そして、すべてを視覚的に見やすく整列させるには、以下を渡しますcolumn

$ gawk 'FNR==1{names[c++]=FILENAME}FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; } END{ for(i=0;i<=c;i++){printf "\t%s",names[i];} printf "\n"; for(i in lines){ print i,lines[i]}}' *Gene.out.tab | column -s$'\t' -t
            SRR3384742.Gene.out.tab  SRR3384743.Gene.out.tab
AT1G01010   301                      151
AT1G01020   622                      683
AT1G01030   149                      63
AT1G03987   0                        0

FNR現在処理中のファイルの行番号を常に保持する特別なawk変数。現在処理中のファイルの名前を保持するFILENAMEGNU特殊変数。awk

  • FNR==1{names[c++]=FILENAME}:これが入力ファイルの最初の行である場合、この変数を値がfilenameの配列のインデックスとして使用し、cその値をyb 1()だけ増やします。すべてのファイルが処理された後は、最初のファイル名、2番目のファイル名などになります。namesc++files[0]files[1]

  • FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; }:これは次のとおりです。

    if(FNR>4){ 
          if("x"lines[$1]){
           lines[$1]"\t"$4
          else{
              lines[$1] = $4
          }
      }
    

    現在の入力ファイルの行番号が5つ以上の場合は、最初のフィールドに配列の関連値があることを確認してくださいlines。使用するかどうかを確認する"x"lines[$i]理由は、テストが偽であるが真であるため、lines[$1]これを防ぐことができるからです。したがって、値がある場合はタブと現在行の2番目のフィールドをここに追加し、値がない場合は現在行の4番目のフィールドに設定します。0x0x

  • END{ ... }:すべての入力が処理された後にこれを実行します。

  • for(i=0;i<=c;i++){printf "\t%s",names[i]}; printf "\n";namesタブ文字の前に配列の各ファイル名を印刷します。先頭タブがヘッダー行とコンテンツのフィールド数を同じにしておきたいと思います。ファイル名を印刷した後、改行文字を印刷します。

  • for(i in lines){print i,lines[i]}:配列の各インデックスにlinesインデックス(ID)を印刷し、最初のステップで保存された関連値を印刷します。

限定:すべての出力データをメモリに保存する必要があります。最新のシステムではIDのみを保存し、ファイルごとにIDごとに1つの値しか保存しないため、これは問題ではありません。したがって、かなりまともなシステムでは、ブロックする前に多くの入力を処理できるはずですが、そうでない可能性があります。問題になる。データ量が多くなると問題があるのが事実だ。

答え2

使用join

join -o '1.1 1.4 2.4' SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
N_unmapped 313860 780346
N_multimapping 5786679 4621162
N_noFeature 438410 362650
N_ambiguous 65902 117293
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63

使用paste

paste私はこれがあなたが探しているものだと思います:

paste <(cut -f 1,4 SRR3384742.Gene.out.tab) <(cut -f4 SRR3384743.Gene.out.tab)
N_unmapped      313860  780346
N_multimapping  5786679 4621162
N_noFeature     438410  362650
N_ambiguous     65902   117293
AT1G01010       301     151
AT1G01020       622     683
AT1G03987       0       0
AT1G01030       149     63

このソリューションでは、すべての項目に次のものを*.tab含める必要があると想定しています。

  1. 行数は同じです。
  2. 同じ順序です。

以下は、ヘッダーを印刷して複数のファイルを処理するスクリプトです。

#!/bin/bash
set -euo pipefail
echo $(printf '%s\t' "$@")
first_file=$1
shift
fifos="<(cut -f1,4 $first_file) "$(printf '<(cut -f4 %s) ' "$@")
eval "paste $fifos"
command *.out.tab
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
N_unmapped      313860  780346
N_multimapping  5786679 4621162
N_noFeature     438410  362650
N_ambiguous     65902   117293
AT1G01010       301     151
AT1G01020       622     683
AT1G03987       0       0
AT1G01030       149     63

答え3

for i in *.tab; do echo $i >/tmp/"$i"_out.txt ; awk '/^AT/{print $1,$4}' $i >> /tmp/"$i"_out.txt ; done
paste /tmp/*_out.txt| awk '{$3="";print }'

出力

SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab 
AT1G01010 301  151
AT1G01020 622  683
AT1G03987 0  0
AT1G01030 149  63

関連情報