joinコマンドの使い方と例:2つのファイルを結合する方法

スポンサーリンク
joinコマンドの使い方と例 ノウハウ
joinコマンドの使い方と例
この記事は約14分で読めます。
よっしー
よっしー

こんにちは、よっしーです(^^)

今日は、joinコマンドをご紹介します。

join コマンドは、UNIXやLinuxシステム上で使用できるテキスト処理のコマンドの1つで、2つのファイルの共通行を結合して出力します(下図参照)。

joinのイメージ図

先日、テキストファイルを結合する必要があり、joinコマンドを使用したので、そのときに使用したコマンドをシェアします。

スポンサーリンク

joinコマンドとは

join コマンドは、UNIXやLinuxシステム上で使用できるテキスト処理のコマンドの1つで、2つのファイルの共通行を結合して出力します。

そのため、join コマンドを使うには、少なくとも2つのファイルが必要です。1つ目のファイルには共通のキーが含まれている必要があり、2つ目のファイルにも同じキーが含まれている必要があります。join コマンドは、指定されたキーを使用して、2つのファイルを結合して、共通の行を出力します。

join コマンドの基本構文は以下の通りです。

join [オプション] ファイル1 ファイル2

join コマンドの一般的なオプションには以下があります。

  • -t : フィールドの区切り文字を指定する。
  • -1 : ファイル1の結合に使用するフィールドを指定する。
  • -2 : ファイル2の結合に使用するフィールドを指定する。
  • -a : ファイル1もしくはファイル2で共通しない行も出力する。
  • -o : 出力するフィールドを指定する。
  • -e : 指定したフィールドがなければ任意の文字列を表示する。
  • -v : ファイル1もしくはファイル2に共通しない行のみを出力する。

以下は、例として file1.txtfile2.txt を結合する方法です。

$ cat file1.txt
1 apple
2 orange
3 banana

$ cat file2.txt
1 red
2 orange
3 yellow

$ join file1.txt file2.txt
1 apple red
2 orange orange
3 banana yellow

-t オプション

joinコマンドの-tオプションは、フィールドの区切り文字を指定するために使用されます。

通常、joinコマンドは、複数のファイルに共通するフィールドを基準にして、それらを結合するために使用されます。デフォルトでは、フィールドはタブ文字によって区切られていることを前提としています。しかし、場合によっては、別の区切り文字を使用している場合もあります。この場合、-tオプションを使用して、適切な区切り文字を指定することができます。

たとえば、次のコマンドは、ファイルfile1.txtとfile2.txtをカンマで区切られたフィールドとして結合します。

% cat file1.txt               
1,apple
2,orange
3,banana

% cat file2.txt               
1,red
2,orange
3,yellow

% join -t, file1.txt file2.txt 
1,apple,red
2,orange,orange
3,banana,yellow

-tオプション無しの場合だと、下記の結果になります。共通のキーはデフォルトの区切り文字が現れるまでの「2,orange」 となります。今回の場合は1行が共通キーとなります。そのため「2,orange」 のキーを持つ行が結合されて、下記のような出力結果にななります。

% join file1.txt file2.txt 
2,orange

-1 オプション

-1 オプションは、ファイル1を結合する際に、使用するフィールドの列番号を指定します。

例えば、file1.txt の 2列目を共通キーとして使用すると下記のようになります。

% cat file1.txt 
1 apple
2 orange
3 banana

% cat file2.txt 
1 red
2 orange
3 yellow

% join -1 2 file1.txt file2.txt 
# 出力なし

file1.txt の 2列目の値と、file2.txt の1列目の値で、共通の値を結合しようとしますが、共通の値がないため、出力結果としては、なしになります。

-2 オプション

-1 オプションと同様に、-2 オプションは、ファイル2を結合するときに使用するフィールドを指定します。

file2.txt の 2列目フィールドを共通キーとして使用した場合も出力なしとなります。

% cat file1.txt 
1 apple
2 orange
3 banana

% cat file2.txt 
1 red
2 orange
3 yellow

% join -2 2 file1.txt file2.txt 
# 出力なし

file1.txt と file2.txt の 2つ目のフィールドを共通キーとして使用した場合は、orangeが結合されて出力されると予想できますが、結果は出力なしとなります。

% cat file1.txt 
1 apple
2 orange
3 banana

% cat file2.txt 
1 red
2 orange
3 yellow

% join -1 2 -2 2 file1.txt file2.txt 
# 出力なし

これは、joinコマンドで結合する際は、共通キーがソートされている必要があるためです。今回の場合だと、2つ目のフィールドがソートされていないため、結合されませんでした。

下記のようにソートして、結合すると期待した結果になります。

% sort -k2,2 -o file1_sort.txt file1.txt

% cat file1_sort.txt 
1 apple
3 banana
2 orange

% sort -k2,2 -o file2_sort.txt file2.txt

% cat file2_sort.txt 
2 orange
1 red
3 yellow

% join -1 2 -2 2 file1_sort.txt file2_sort.txt
orange 2 2

-a オプション

joinコマンドの-aオプションは、一方のファイルにしか存在しない行(ファイル1またはファイル2)も出力するように指定するオプションです。

-aオプションには、以下の2つの引数を指定できます。

  • -a 1: ファイル1にしか存在しない行も出力する
  • -a 2: ファイル2にしか存在しない行も出力する

また、-aオプションは、joinコマンドを実行する前に、ファイルをソートする必要があります。ソートされていないファイルをjoinコマンドに渡すと、正しい結果が得られない可能性があります。

以下は、-a 1オプションを使用してjoinコマンドを実行する例です。ファイル1にしか存在しない行(つまり、file1.txtの4行目)も出力されます。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 1 file1.txt file2.txt 
1 apple red
2 orange orange
3 banana yellow
4 grape

同様に、-a 2オプションを使用すると、ファイル2にしか存在しない行が出力されます。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 2 file1.txt file2.txt 
1 apple red
2 orange orange
3 banana yellow
5 black

また、-a 1 -a 2オプションを使用すると、ファイル1もしくはファイル2にしか存在しない行が出力されます。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 1 -a 2 file1.txt file2.txt 
1 apple red
2 orange orange
3 banana yellow
4 grape
5 black

-o オプション

joinコマンドの-oオプションは、出力するフィールドの形式を指定するために使用されます。

-oオプションには、以下のような形式で指定します。

-o <オプション>

<オプション>には、以下の値を指定できます。

  • 0:結合に使用したフィールドを出力します。
  • 1.1:ファイル1の1列目のフィールドを出力します。
  • 1.2:ファイル1の2列目のフィールドを出力します。
  • 2.1:ファイル2の1列目のフィールドを出力します。
  • 2.2:ファイル2の2列目のフィールドを出力します。
  • 2.1:2番目のファイルの最初のフィールドを出力します。
  • その他の値:-oオプションで指定されたフィールドをカンマで区切って出力します。たとえば、-o 1.1,1.2,2.2と指定すると、ファイル1の1列目と2列目のフィールド、およびファイル2の2列目のフィールドを出力します。

以下は、-oオプションを使用してjoinコマンドを実行する例です。ファイル1(file1.txt)は「ID」と「商品名」の2つのフィールドを持ち、ファイル2(file2.txt)は「ID」と「色」の2つのフィールドを持ちます。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt 
1 red
2 orange
3 yellow
5 black

% join -o 1.2,2.2 file1.txt file2.txt
apple red
orange orange
banana yellow

この例では、-o 1.2,2.2を使用して、ファイル1の2列目のフィールド(商品名)とファイル2の2列目のフィールド(色)を出力しています。

-e オプション

-e オプションは、指定したフィールドがなければ任意の文字列を表示する時に使用します。-o オプションと合わせて使用する必要があります。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 1 -e xxx -o 1.2,2.2 file1.txt file2.txt
apple red
orange orange
banana yellow
grape xxx

-v オプション

joinコマンドの-vオプションは、指定されたファイルに存在するが、結合先のファイルには存在しない行を抽出するために使用されます。

具体的には、-vオプションには、1または2を指定することができます。-v 1は、ファイル1に存在し、ファイル2には存在しない行を抽出し、-v 2は、ファイル2に存在し、ファイル1には存在しない行を抽出します。

-v 1オプションを使用してjoinを実行すると、ファイル1に存在し、ファイル2には存在しない行(ここでは、4 grape)が抽出されます。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -v 1 file1.txt file2.txt
4 grape

同様に、-v 2オプションを使用すると、ファイル2に存在し、ファイル1には存在しない行(ここでは、5 black)が抽出されます。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -v 2 file1.txt file2.txt
5 black

応用

左外部結合

リレーショナル・データベースにおける LEFT OUTER JOIN をjoinコマンドで表現すると下記のようになります。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 1 -e NULL -o 0,1.2,2.2 file1.txt file2.txt
1 apple red
2 orange orange
3 banana yellow
4 grape NULL

右外部結合

リレーショナル・データベースにおける RIGHT OUTER JOIN をjoinコマンドで表現すると下記のようになります。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 2 -e NULL -o 0,1.2,2.2 file1.txt file2.txt
1 apple red
2 orange orange
3 banana yellow
5 NULL black

完全外部結合

リレーショナル・データベースにおける FULL OUTER JOIN をjoinコマンドで表現すると下記のようになります。

% cat file1.txt 
1 apple
2 orange
3 banana
4 grape

% cat file2.txt
1 red
2 orange
3 yellow
5 black

% join -a 1 -a 2 -e NULL -o 0,1.2,2.2 file1.txt file2.txt
1 apple red
2 orange orange
3 banana yellow
4 grape NULL
5 NULL black

複数フィールドでの結合

複数フィールドを共通キーとしてjoinしたい場合は、複数フィールドを結合したフィールドを用意してjoin します。下記がその例になります。

% cat file1.txt                                    
shopA 1 apple
shopB 1 apple
shopA 2 orange
shopB 2 orange
shopA 3 banana
shopB 4 grape

% awk '{print $1 "-" $2, $0}' file1.txt > file1_v2.txt

% sort -k1,1 -o file1_sort.txt file1_v2.txt           

% cat file1_sort.txt 
shopA-1 shopA 1 apple
shopA-2 shopA 2 orange
shopA-3 shopA 3 banana
shopB-1 shopB 1 apple
shopB-2 shopB 2 orange
shopB-4 shopB 4 grape

% cat file2.txt                                       
shopA 1 red
shopB 1 red
shopA 2 orange
shopB 2 orange
shopA 3 yellow
shopA 5 black

% awk '{print $1 "-" $2, $0}' file2.txt > file2_v2.txt

% sort -k1,1 -o file2_sort.txt file2_v2.txt

% cat file2_sort.txt                  
shopA-1 shopA 1 red
shopA-2 shopA 2 orange
shopA-3 shopA 3 yellow
shopA-5 shopA 5 black
shopB-1 shopB 1 red
shopB-2 shopB 2 orange

% join file1_sort.txt file2_sort.txt                  
shopA-1 shopA 1 apple shopA 1 red
shopA-2 shopA 2 orange shopA 2 orange
shopA-3 shopA 3 banana shopA 3 yellow
shopB-1 shopB 1 apple shopB 1 red
shopB-2 shopB 2 orange shopB 2 orange

# -o オプションで出力するフィールドを指定すると見やすくなります
% join -o 0,1.4,2.4 file1_sort.txt file2_sort.txt
shopA-1 apple red
shopA-2 orange orange
shopA-3 banana yellow
shopB-1 apple red
shopB-2 orange orange

おわりに

今日は、joinコマンドについてご紹介しました。

いざというときに役に立ったりするので、頭の片隅にでもこんなコマンドがあったなと覚えておくといいと思います。その時は、このサイトを見返してもらえると嬉しいです。

よっしー
よっしー

またあしたお会いしましょう!!

コメント

タイトルとURLをコピーしました