特定のフィールドに基づいて2つの異なるファイルから一意の行を見つける

特定のフィールドに基づいて2つの異なるファイルから一意の行を見つける

複数行を含む2つのtxtファイルを比較し、ファイル1に固有の行のみを含む3番目のtxtファイルを作成する必要があります。ファイル1の例は次のとおりです。

../../A/folder/fname.gz | -12.36 | A:BCD:123:A, D:DFR:241:AZ1 
../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

数千行にわたって続き、ファイル2の例は次のとおりです。

../../B/folder2/fname.gz | -7.65 | C:ABC:425:A
../../B/folder2/fname3.gz | -12.31 | A:BCD:758:D

../../folder/fname2.gz例のように、最初のフィールドに基づいて一意のファイル1のすべての行を取得する必要があります。異なるfolder場合がありますが、固有でなければfnameX.gzなりません。folder両方ともおよび/またはをfname含みます。各行のフィールド数は異なる場合があります。上記の例の予想出力は次のとおりです。-_

../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

これを行う最良の方法は何ですか?

答え1

awk -F ' *[|] *' '{ k=$1; sub(".*/", "", k) }
               !z { a[k]; next } !( k in a )' file2 z=1 file1

まず読み込み、file2ファイル名部分を配列に保存します。読み込み時にfile1ファイル名が配列にない場合は、1行を印刷します。

答え2

私たちはシュワルツ変換|各ファイルの最初のフィールドのファイル名に文字が含まれておらず、フィールドがオプションのスペース|(スペースおよび/またはタブ)で囲まれていると仮定するヘルパーシェル関数。

sorterまず、入力データの最初のフィールドからファイル名を抽出し、データをソートする前に、各行にこのファイル名プレフィックスを追加するヘル​​パー関数を定義します。

sorter () {
    awk -F '[[:blank:]]*\|[[:blank:]]*' -v OFS='|' \
        '{ key=$1; sub(".*/","",key); print key, $0 }' |
    sort
}

$0最終出力で最初のフィールドのパス名のみが必要な場合は、上記の$1コードでを変更してください。$22番目のフィールドなどをインポートするように変更します。

joinユーティリティは入力が結合フィールドに従ってソートされると仮定するため、データをファイル名でソートする必要があります。

この関数は標準入力からデータを読み込み、最初のファイルを実行すると結果は次のようになります。

$ sorter <file1
fname.gz|../../A/folder/fname.gz | -12.36 | A:BCD:123:A, D:DFR:241:AZ1
fname2.gz|../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

各入力ファイルに対してこれを行い、最初のフィールド結合を使用すると、次を使用して、2番目のファイルのどの行ともペアリングできない最初のファイルの行のみを出力するようにjoin要求できます。joinjoin -v 1

join -t '|' -v 1 <( sorter <file1 ) <( sorter <file2 ) | cut -d '|' -f 2-

最後に、このコマンドは、コマンドが各行に追加したcutファイル名フィールドを削除します。awk

質問のデータを考慮すると、結果は次のようになります。

../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

コードを$0次に置き換えると、次のような結果が得られます。$1awk

../../A/folder/fname2.gz

関連情報