複数のファイルの特定の列を結合する方法

複数のファイルの特定の列を結合する方法

データファイルがありますA.tsv(フィールド区切り記号= \t)。

id  clade   mutation
243 40A SDF
254 20B
261 40A
267 20B

B.tsv(フィールド区切り記号 = \t):

id  clade   mutation
243 40A
254 20B
261 40A
267 20B SLT

C.tsv(フィールド区切り記号 = \t):

id  clade   mutation
243 40A
254 20B
261 40A MGG
267 20B

すべてのファイル間で他の唯一の列は列であることを知り、すべてのファイルを1つにリンクしたいと思いますmutation。予想される結果は次のとおりです。

id  clade   mutation
243 40A SDF
254 20B
261 40A MGG
267 20B SLT

これまで私は次のことを試しました。

awk 'BEGIN{FS=OFS="\t"} NR==FNR{klos[NR]=$3; next} $3==""{$3=klos[FNR]} 1' *.tsv > output.tsv

しかし、うまくいきません。する方法はありますか?ありがとう

PS:これはサンプルテストです。実際には3つ以上のファイルがあります。ただし、例と同様に、mutationその列に同じ内容を持つ2つのファイルはありません。

答え1

すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ cat tst.awk
BEGIN { FS=OFS="\t" }
(NR == FNR) || ($3 != "") {
    fnr2rec[FNR] = $0
}
FILENAME == ARGV[ARGC-1] {
    print fnr2rec[FNR]
}

$ awk -f tst.awk A.tsv B.tsv C.tsv
id      clade   mutation
243     40A     SDF
254     20B
261     40A     MGG
267     20B     SLT

答え2

次に、次を使用してpaste出力を処理しますawk

paste file[ABC].tsv |\
awk 'BEGIN{ FS=OFS="\t" } { for(i=3; i<=NF; i+=3) if($i"")break; print $1, $2, $i }'

使用される条件は、if($i"")breaknull以外の最初のフィールドが見つかった場合にforループを中止し(awkに文字列比較を実行させるには二重引用符を使用します)、フィールド#1、#2、および以前に見つかったnull以外のフィールドのみを印刷します。することです。フィールド#iパスにあります。

答え3

これは効果があります(反対の結果が気に入らない場合)。

[root@SE ~]# awk 'BEGIN{FS=OFS="\t"} { if($3>0) { print }}' A.tsv B.tsv C.tsv | sort -ru

私は慣れていないので、おそらくこれを達成するより簡単な方法があると確信していますawk

私がしたことは、3つのファイルをすべて印刷し、バリアントから文字を持たないすべての行を削除することだけでした。その後、パイプラインはsort -uすべての重複エントリを削除します。この-rフラグは順序を逆にします。

[root@SE ~]# awk 'BEGIN{FS=OFS="\t"} { if($3>0) { print }}' A.tsv B.tsv C.tsv | sort -ru
id  clade   mutation
267 20B SLT
261 40A MGG
254 20B SLT
243 40A SDF

@Quasimodoはこれを単純化しました。ありがとうございます。

awk 'BEGIN{FS=OFS="\t"} (FNR>1 || NR==1) && $3' A.tsv B.tsv C.tsv

処理された最初の行(つまり、最初の入力ファイルのヘッダー)または処理されたすべての行の場合は、1行を印刷します。いいえヘッダーですが空ではない3番目のフィールドが含まれています。{ ... }ルールブロック()の外側のブール式が「true」と評価され、awk現在の行を印刷する必要があることを示すために機能します。

答え4

Bashコマンドラインユーティリティを使用する1つの方法は次のとおりです。

## initialization 
ref= tmpdir=$(mktemp -d) cn=3

for f in ./*.tsv;do
  : ${ref:="$f"}
 < "$f" cut -f"$cn" > "$tmpdir/$f"
done

paste <(cut -f-"$((cn-1))" "$ref") "$tmpdir"/* |
tr -s '\t' |
sed -ne "1s/\t/\n/$cn" -e 's/\t*$//;P'

結果:

id  clade   mutation
243 40A SDF
254 20B
261 40A MGG
267 20B SLT

関連情報