awkを使用して2つのファイルの2つの列を比較し、一致しないパターンを印刷する方法

awkを使用して2つのファイルの2つの列を比較し、一致しないパターンを印刷する方法

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

id  clade   mutation
243 40A siti,toto,mumu
254     
267 40B lala,sisi,sojo

とテンプレートファイルB.tsv(フィールド区切り記号= \t):

40A toto,xixi,saxa
40B lala,sojo,huhu
40C sasa,sisi,lala

共通のcladeに基づいてA.tsvテンプレートの突然変異を比較したいと思いますB.tsv。 2つの質問があります。

  1. B.tsv「missing_mutation」という新しい列に存在しない突然変異の名前をどのように表示できますかA.tsv
  2. A.tsvに存在するが(文字で始まりs、大文字と小文字を区別しない)には、存在しない突然変異の名前を "remaining_mutation"という新しい列にどのように表示できますかB.tsv

C.tsv次のようになります。

id  clade   mutation    missing_mutation    remaining_mutation
243 40A siti,toto,mumu  xixi,saxa   siti
254     
267 40B lala,sisi,sojo  huhu    sisi

次のように2つのファイルを比較する方法を知っています。

awk -F"," -vOFS="," '    
    NR==FNR {
     a[$2]=$3;
     next
    }
    
    { print $0,a[$2] }
' B.tsv A.tsv > C.tsv

しかし、一致しないアイテムを印刷する方法がわかりません。良いアイデアがありますか?

ベストアンサー1

次のawkプログラムは、便宜上awk(「真の二重インデックス配列」の形で)GNUを使用しており、この問題を解決する必要があります。これは、2つのファイルを引数として使用して順番に呼び出すことを目的としていますB.txt A.txt(コード例で行ったのと同じように)。

#!/bin/awk -f

BEGIN{FS=OFS="\t"}

NR==FNR {
    n_tmp[$1]=split($2,buff,/,/)
    for (i=1;i<=n_tmp[$1];i++) mut_tmp[$1][i]=buff[i]
    next
}

FNR==1 {
    print $0,"missing_mutation","remaining_mutation"
}

FNR>1 {
    n_curr=split($3,mutations,/,/)
    mut_miss=0
    mut_rem=0

    # Find missing
    for (j=1;j<=n_tmp[$2];j++)
    {
        for (i=1;i<=n_curr;i++)
        {
            if (mutations[i]==mut_tmp[$2][j]) break
        }
        if (i>n_curr) mut_miss=mut_miss ? mut_miss "," mut_tmp[$2][j] : mut_tmp[$2][j]
    }

    # Find remaining
    for (i=1;i<=n_curr;i++)
    {
        for (j=1;j<=n_tmp[$2];j++)
        {
            if (mutations[i]==mut_tmp[$2][j]) break;
        }
        if (j>n_tmp[$2] && mutations[i]~/^[Ss]/) mut_rem=mut_rem ? mut_rem "," mutations[i] : mutations[i]
    }
    
    if (!mut_miss) mut_miss=""
    if (!mut_rem) mut_rem=""

    print $0,mut_miss,mut_rem
}
  • これにより、最初にclade nrの相関テーブルが作成されます。テンプレートを解析するときは、それを突然変異リストと比較してくださいB.tsv。ここで、テンプレート突然変異リストは明示的に個々の突然変異配列に分割される。便宜上、mut_tmp最初のインデックスが分岐番号の「デュアルインデックス」配列を使用していることに注意してください。 2番目は、突然変異のインデックス番号です。突然変異の数も配列に保存されますn_tmp
  • 解析するときは、A.tsv新しいヘッダーを最初に印刷します。
  • 次に、各行に対して最初にフィールド3のバリアントリストを配列に分割しますmutations
  • 次に、現在のクレード()のテンプレート突然変異リスト内の各項目を既存のmut_tmp[$2]突然変異()とmutations比較して、「欠落突然変異」フィールドを埋めます。
  • s次に、現在のバリエーションリストの各項目を現在のクレードのテンプレートバリエーションと比較して、「残りのバリエーション」フィールドを埋め、バリエーションがまたはで始まることを確認しますS

GNUが利用できない場合は、次のものを置き換えて他awkのほとんどの実装で動作させることができます。awk

mut_tmp[a][b]

そして

mut_tmp[a,b]

\034これは、系統番号と突然変異名が基本的に個々のコンポーネントを単一の文字列配列インデックスに関連付けるために使用される特殊文字を含まないように見えるために機能します(SUBSEP詳細は内部変数を参照してください)。

入力例の出力は次のとおりです。

~$ awk -f compare.awk B.tsv A.tsv 
id  clade   mutation    missing_mutation    remaining_mutation
243 40A siti,toto,mumu  xixi,saxa   siti
254             
267 40B lala,sisi,sojo  huhu    sisi

例で必要な出力が要件の説明と一致しません。

編集する

A.tsv実際、四半期群は22列にあり、突然変異は41列にあることをあなたの意見で指摘したので変更してください。

  • split($3,mutations,/,/)到着split($41,mutations,/,/)
  • すべてのn_tmp[$2]発生n_tmp[$22]
  • mut_tmp[$2][j](または[$2,j])からmut_tmp[$22][j](または[$22,j])までのすべての項目

おすすめ記事