小さいファイルと大きいファイルの間で一致する値と一致しない値をマージして印刷します。

小さいファイルと大きいファイルの間で一致する値と一致しない値をマージして印刷します。

次のように比較的小さなスペースで区切られたファイルがあります(ただし、多くの列と行があります)。

ファイル1:

Entry1
a
b
c
d

次のように、1行に多くの重複項目がある別の巨大なタブ区切りファイルです。

ファイル2:

value       ID1   ID2   
1      a    aaaa1
1      a    aaaa2
1      b    bbbb1
1      b    bbbb2
1      b    bbbb3
1      d    aaaa4

まず、以下のように、file1の各項目とfile2のID1フィールド(列2)の間の一致を指定して、file1と同じサイズのタブで区切られたファイルを印刷しようとします。これは別の質問です。:

Entry1
a
b
NoMatch
d

また、file1とfile2の値を含むマージタブで区切られたファイルを印刷します。今回はfile2に重複した項目がありますが、次のようにNoMatchも保持します。

value       ID1   ID2   
1      a    aaaa1
1      a    aaaa2
1      b    bbbb1
1      b    bbbb2
1      b    bbbb3
NoMatch NoMatch NoMatch
1      d    aaaa4

Joinコマンドを使用しようとすると、NoMatchメッセージが表示されます。

join -a1 -e "NoMatch" <(awk -F ' ' '{print $0}' file1.txt |tail -n +2|sort -k1,1) <(cat file2 | sort -k1,1) > out.txt

しかし、これはfile1のすべての内容を印刷するので何か間違っているようです。ただし、file2に一致するものがない場合、残りのフィールドは空です(したがって、「NoMatch」というメッセージは表示されません)。私がどんな人なのかを理解するのに役立ちますか?何か間違っていましたか?

とても感謝しています!

#

Gilesさん、ありがとうございます。今すぐ参加したので、あなたの意見に答えることができないようです...あなたの提案は次のとおりです。

join -a1 -e "NoMatch" -11 -22 --header -o2.1,2.2,2.3 file1 file2

2番目のクエリOutput2を修正しました。ありがとうございます! file1と同じ行を持つ最初のOutput1を取得する方法を尋ねてください。もう一度ありがとうございます! !

don_crisstiの助けを借りて、次の2番目の出力を得ることができます。

paste -d'\t' file2 <(awk 'FNR==NR{seen[$1]++; next}  {(FNR==1 || ($1 in seen)) || $1="NoMatch"};1'  file2  file1)

答え1

読みやすくするために、元の例の形式を再指定します。

join -a1 -e "NoMatch" \
 <(awk -F ' ' '{print $0}' file1.txt |tail -n +2|sort -k1,1) \
 <(cat file2 | sort -k1,1)

すべての問題はjoinfile2の処理とオプションに関連しています。

  1. file2は、フィールド1(フィールド2でなければならない)に基づいてソートされます。
  2. -t '<tab>'options がない場合、joinfile2 はタブで区切られます。
  3. joinfile2フィールド2を結合するオプションがありません。
  4. file2のフィールドが正しい場合でも、デフォルトのjoin出力はリンクされたフィールドを最初に印刷するため、オプションを指定する-o FORMAT必要がありますjoin
  5. file2 ヘッダーは削除されません。
  6. 問題は発生しませんが、処理は不要です。最初の行をスキップできるため、tailfile1には必要ありません。awk
  7. -F ' 'オプションは必要ありませんawk

これらの問題を修正すると、次の結果が得られます。

#!/bin/bash
head -1 file2
join -t '   ' -2 2 -a 1 -e NoMatch -o 2.1,2.2,2.3 \
 <(awk 'NR==1{next} {print $0}' file1.txt | sort) \
 <(tail -n +2 file2 | sort -k2)

これにより、タブで区切られた次の出力が生成されます。

value   ID1     ID2
1       a       aaaa1
1       a       aaaa2
1       b       bbbb1
1       b       bbbb2
1       b       bbbb3
NoMatch NoMatch NoMatch
1       d       aaaa4

関連情報