3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シェルスクリプトのjoinコマンドでcsv,tsvファイルのinner joinとleft join

Last updated at Posted at 2020-05-04

はじめに

複数のデータベースやシステムにデータがまたいでいるとき、それらのデータをidかなにかで結合したいときがあります。

自分のlocalにDBいれて、とりこんでしまえばSQLで結合するのは難しくないです。
そこまでするほどでないとか、DBに取り込むにはデータが多すぎるときは、シェルでさくっとやりたいことがあります。

joinコマンドのバージョン

次のもの以降なら問題ないと思います。古いバージョンだと、一部使えない機能があります。

$ join --version
join (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel.

内部結合(inner join)

ヘッダーありの場合は--headerオプションをつけます。
区切り文字は-tでいけます。 csvなら-t, でいけます。tsvの場合はタブ文字を認識させるために、-t $'\t' とします。

ファイルの例としては、tsvで、ダブルクォートを囲み文字のものとします

test1.tsv
$ cat test1.tsv
"id"    "name"
"1"     "test 1"
"2"     "test 2"
"3"     "test 3"
"4"     "test 4"
sample.tsv
$ cat sample.tsv
"id"    "tel"
"2"     "031234567"
"4"     "123456789"
$ join --header -t $'\t' test1.tsv sample.tsv
"id"    "name"  "tel"
"2"     "test 2"        "031234567"
"4"     "test 4"        "123456789"

左外部結合(left join)

-aオプションで、マッチしないものも残すファイルを指定します。
左側を残した場合は-a 1 になります。

$ join --header -t $'\t' -a 1 test1.tsv sample.tsv
"id"    "name"  "tel"
"1"     "test 1"
"2"     "test 2"        "031234567"
"3"     "test 3"
"4"     "test 4"        "123456789"

これだと、マッチしなかった行について、右側のファイルにあるカラムがかけてしまいます。
そのときは、-oオプションと一緒に、-eオプションを使うことで指定できます。
とくになければ -o auto をするのが便利です。両方のファイルのカラムがすべてでます。
(古いバージョンだと、これが使えないので注意)

$ join --header -t $'\t' -a 1 -o auto -e '""' test1.tsv sample.tsv
"id"    "name"  "tel"
"1"     "test 1"        ""
"2"     "test 2"        "031234567"
"3"     "test 3"        ""
"4"     "test 4"        "123456789"

cross join

あまり使う場面がなさそうですが、両方のファイルのidを残したい場合があります。
いわゆるcross join相当をしたいときです。
-a 1 -a 2でできます。

$ cat sample2.tsv
"id"    "tel"
"2"     "031234567"
"4"     "123456789"
"5"     "050XXXXYYYY"
"6"     "06XXXXYYYY"
$ join --header -t $'\t' -a 1 -a 2 -o auto -e '""' test1.tsv sample2.tsv
"id"    "name"  "tel"
"1"     "test 1"        ""
"2"     "test 2"        "031234567"
"3"     "test 3"        ""
"4"     "test 4"        "123456789"
"5"     ""      "050XXXXYYYY"
"6"     ""      "06XXXXYYYY"

除外処理

除外したいIDのリストをファイルでもっていて、IDがその除外リスト以外のものだけを抽出したいケースがあります。
-vオプションで残したいファイルの方を指定するだけです。

exclude.tsv
"id"
"2"
"3"
$ join --header -t $'\t' -v 1  test1.tsv exclude.tsv
"id"	"name"
"1"	"test 1"
"4"	"test 4"

参考リンク

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?