当社の
CTOから出題されるクイズの整理と書き留めを行いたいと思います。
【CTOからの1日1問】 2016/06/17
今回はデータ整形に便利なコマンドの問題です。
クラス全員の学籍番号と氏名が学籍番号順に並んだテキストファイルname.txtがある。
1 山田太郎
2 田中二郎
3 中田三郎
クラス全員の学籍番号と趣味が学籍番号順に並んだテキストファイルhobby.txtがある。
1 釣り
2 読書
3 映画鑑賞
この二つのファイルを結合して、以下のような内容のテキストファィルname_hobby.txtを作成したい。
1 山田太郎 釣り
2 田中二郎 読書
3 中田三郎 映画鑑賞
以下の下線部に当てはまるコマンドはなにか。
____________ name.txt hobby.txt > name_hobby.txt
[正解]
join
ですね。
1 山田太郎 釣り
2 田中二郎 読書
3 中田三郎 映画鑑賞
という結果は、先頭の列だけに学績番号が出力されています。このような結合をおこなう時に使いたい場合はjoinになりますね。
pasteだとそれぞのファイルを単純に横に連結するだけになってしまうので学績番号はそのままダブって表示されてしまいます。
今回のクイズに関連して、テキストデータの整形の中でも結合を行うコマンドである
joinと
paste、
catについて整理しておきたいと思います。
1.ファイルを横に結合
join:join - 二つのファイルを読み、フィールドが共通な行を結合する
パターン1:
先頭行で結合。
デフォルトの動作では、 join フィールドは各行の先頭に来る。
$ cat name
1 Aaron
2 Barry
3 Calvin
4 Dan
$ cat hobby
1 fishing
2 reading
3 running
4 swimming
$ join name hobby
1 Aaron fishing
2 Barry reading
3 Calvin running
4 Dan swimming
パターン2:
join フィールドを指定して結合。
なお、join フィールドの昇順にソートしておかなければならない (数値順のソートはだめ)。
オプション
-1 FIELD, -j1 FIELD
FILE1 の FIELD 番目のフィールドを用いて join を行う (FIELD は正
の整数)。
-2 FIELD, -j2 FIELD
FILE2 の FIELD 番目のフィールドを用いて join を行う (FIELD は 正
の整数)。
$ cat name
1 Aaron 2
2 Barry 4
3 Calvin 1
4 Dan 3
$ cat hobby
1 fishing
2 reading
3 running
4 swimming
$ sort -k3 name > name_after_sort
$ cat name_after_sort
3 Calvin 1
1 Aaron 2
4 Dan 3
2 Barry 4
$ join -1 3 -2 1 name_after_sort hobby
1 3 Calvin fishing
2 1 Aaron reading
3 4 Dan running
4 2 Barry swimming
パターン3:
ペアにならなかった行も含めて結合。
-a FILE-LIST
FILE-NUMBER (‘1’ または ‘2’) のファイルにあるペアにならなかった
行を、通常の出力に追加して表示する。
$ cat name_after_sort
3 Calvin 1
1 Aaron 2
4 Dan 3
2 Barry 4
$ cat hobby
1 fishing
2 reading
3 running
4 swimming
5 cycling
$ join -1 3 -2 1 name_after_sort hobby
1 3 Calvin fishing
2 1 Aaron reading
3 4 Dan running
4 2 Barry swimming
$ join -1 3 -2 1 -a 2 name_after_sort hobby
1 3 Calvin fishing
2 1 Aaron reading
3 4 Dan running
4 2 Barry swimming
5 cycling
パターン4:
ペアにならなかった行だけ表示。
-v FILE-NUMBER
通常の出力ではなく、 FILE-NUMBER (‘1’ または ‘2’) のファイルにあ
る、ペアにならなかった行だけを表示する。
$ cat name_after_sort
3 Calvin 1
1 Aaron 2
4 Dan 3
2 Barry 4
$ cat hobby
1 fishing
2 reading
3 running
4 swimming
5 cycling
$ join -1 3 -2 1 name_after_sort hobby
1 3 Calvin fishing
2 1 Aaron reading
3 4 Dan running
4 2 Barry swimming
$ join -1 3 -2 1 -v 2 name_after_sort hobby
5 cycling
パターン5:
キーを比較するときに英大文字小文字の違いを無視する。
-i, --ignore-case
キーを比較するときに英大文字小文字の違いを無視する。このオプショ
ンを指定するときは、入力ファイルも同じように整列させておかなけれ
ばならない。このような整列を行うには ‘sort -f’ を使えば良い。
$ cat name
1 Aaron 2 Usa
2 Barry 4 Uk
3 Calvin 1 Nzl
4 Dan 3 Aus
$ cat country
1 USA UnitedStates
2 UK UnitedKingdom
3 NZL NewZealand
4 AUS Australia
$ join -1 4 -2 2 -i name country
Usa 1 Aaron 2 1 UnitedStates
Uk 2 Barry 4 2 UnitedKingdom
Nzl 3 Calvin 1 3 NewZealand
Aus 4 Dan 3 4 Australia
paste:paste - ファイルを行単位でマージする
$ cat name
1 Aaron
2 Barry
3 Calvin
4 Dan
$ cat hobby
1 fishing
2 reading
3 running
4 swimming
$ paste name hobby
1 Aaron 1 fishing
2 Barry 2 reading
3 Calvin 3 running
4 Dan 4 swimming
2.ファイルを縦に結合
cat:cat - ファイルを連結して出力する
$ cat name
1 Aaron
2 Barry
3 Calvin
4 Dan
$ cat hobby
1 fishing
2 reading
3 running
4 swimming
$ cat name hobby
1 Aaron
2 Barry
3 Calvin
4 Dan
1 fishing
2 reading
3 running
4 swimming
以上です!
【参考サイト】
『Linuxコマンドでテキストデータを自在に操る』
『joinコマンドが便利過ぎて生きるのが辛い』