過ごしやすい季節から段々暑い日が多くなってきましたね.
暑いのが苦手な夏生まれのh--ishiです.
最近,複数テキストファイル(表データ)をLinuxのjoinコマンドで連結することがあり,
少し手間取ったので備忘録として書き遺しておきます.
joinとは...
二つのテキストファイルの共通のキーをもつ行を連結して,一つの行にまとめてくれるLinuxのコマンドです
具体例をだして,やっていきたいと思います.
下のような,店A,Bでの肉の商品名とその値段に関する二つの表があったとします.
これらの表を一つの表にまとめたい!ということですね.
(実際には,2つのサンプルの実験結果の表を1つの表にまとめるということが想定されそうです.)
お店Aでのお肉の価格(storeA.txt)
商品名 店Aでの値段(JPY) ゴブリンの肉 100 ベヒーモスの肉 500 ガーゴイルの肉 1000
お店Bでのお肉の値段(storeB.txt)
商品名 店Bでの値段(JPY) ゴブリンの肉 100 ベヒーモスの肉 50 ガーゴイルの肉 2000 キマイラの肉 10000
上の2ファイルをjoinコマンドで連結してみましょう
$ join -a 1 -a 2 -j 1 -o 1.1,1.2,2.2 -e NA --header storeA.txt storeB.txt > merge.txt
用いたオプションは
-a
: 参照したファイル間で共通していない行も出力(-a 1 の場合,storeAに特有の行も出力する)
-j
: 参照したファイル間において比較する列番号(今回は商品名でまとめるので,"1"です)
-o
: 各参照ファイルの出力する列番号(1.1,1.2,2.2だと1「個目のファイルの1列目と2列目,2個目のファイルの2列目を出力する」という意味.)
-e
: 共通していない行について,カラムにいれる文字を指定する(今回の場合NAを入れた)
--header
: 一行目をヘッダーと認識する
- ハマった点1:joinはsortする必要がある!
僕はこれを知らずにjoinを行ないまして,ソートしてくださいと怒られました.
(僕がつくった上の表では元々ソートされた状態で作ってしまったので怒られませんでしたが,実際に扱っているデータでは怒られました.)
ファイルの行のソートは,sortコマンドで行います.
- ハマった点2: sortはheaderを認識してくれない!!!
怒られてしまいましたので,仕方ない...sortを行います.
$ sort storeA.txt ガーゴイルの肉 1000 ゴブリンの肉 100 ベヒーモスの肉 500 商品名 店Aでの値段(JPY)
ヘッダーもソートされてしまった...もはやヘッダーではない!
オプションを探しても,ヘッダーを認識するオプションはなさそう...
人力で,ヘッダー行を削ってsortしてあとからヘッダーをつけるなども考えられますが,面倒ですよね?
なので,こんな作戦がたてられます.
1. head
コマンドでヘッダーを抽出する
2. tail
コマンドでヘッダー以外を抽出したものをソートする
3. 1. と2. とを子bashで実行して連結する
$ (head -n 1 storeA.txt && tail -n +2 storeA.txt | sort ) > storeA_sorted.txt
ヘッダーがあるソート済みファイルが完成しました.
商品名 店Aでの値段(JPY) ガーゴイルの肉 1000 ゴブリンの肉 100 ベヒーモスの肉 500
$ join -a 1 -a 2 -j 1 -o 0 1.1,1.2,2.2 -e NA --header storeA_sorted.txt storeB_sorted.txt > merge.txt
商品名 店Aでの値段(JPY) 店Bでの値段(JPY) ガーゴイルの肉 1000 2000 NA NA 10000 ゴブリンの肉 100 100 ベヒーモスの肉 500 50
以上,僕が二つのファイルをjoinコマンドでつまづいた赤裸々告白でした(照)