それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

join コマンドでLEFT OUTER JOIN のNULL 付きで出して、会議ごとの出席者一覧データを作る。

join コマンドでLEFT OUTER JOIN のNULL 付き的なことをやる

会議の出席の記録や、商品の売上のようなデータを横展開して表にしたい時がある。

このようなとき、join コマンドをぱぱっと実行すれば、データのOUTER JOIN的な事ができる。

出席と欠席を join コマンドで

join 2021-08-11.txt   2021-07-11.txt
A100 出席 出席
A101 出席 出席
A102 出席 欠席
A103 出席 欠席
A104 出席 欠席
A105 出席 欠席

しかし、整理されてない場合や、存在しないデータ(NULL・EMPTY)はいちいち書かない。

次のように、出席だけを書く場合が多いと思う。

出席だけを書いている

cat  2021-07-11-出席者のみ.txt
A100 出席
A101 出席

会議の出席者をメモったテキストがあるとする。

これをJOINするときに、NULLに相当する空文字を埋めてあげれば、データとして処理することができる。

出席や提出は出した人だけをメモっていることが多いですよね。まさか未提出を未提出、未払いを未払いとわざわざメモる人は少ないでしょう。

また、フォルダやファイルを探して見つかったものを集計することがおおく、未出現のIDはデータとして出てきません。

先に、欠席を補完する

そこで、未出現をEMPTYやNULLなど、データ欠損を埋めてデータ処理に適した形式にする。

join -a 1 -o auto -e '欠席' id.txt 2021-07-11-出席者のみ.txt
A100 出席
A101 出席
A102 欠席
A103 欠席
A104 欠席
A105 欠席

または、わかりやすいように NULL の文字で埋めてあげる。

join -a 1 -o auto -e 'NULL' id.txt 2021-07-11-出席者のみ.txt
A100 出席
A101 出席
A102 NULL
A103 NULL
A104 NULL
A105 NULL

この処理を冒頭処理と同等に一回で行う

join -a 1  2021-08-11.txt   <(join -a 1 -o auto -e '欠席' id.txt 2021-07-11-出席者のみ.txt)

join コマンドは、 join <( サブコマンド)のカタチで複数回のネストをするこができる。

複数の処理

しかし実際には、サブコマンドでは不便で。

JOINを join *.txt のような、引数を複数ファイルで行うことが出来ない。

事前処理をして、さらに関数を作ってあげれば、join *.txtのような処理で複数ファイルを使うことで実現する。

function multijoin() {
    out=$1
    shift 1
    cat $1 | awk '{print $1}' > $out
    for f in $*; do join $out $f > tmp; mv tmp $out; done
}
multijoin 出席者一覧 *.txt
cat 出席者一覧

NULLを入れてあげるちょっとした事前処理

このような、ちょっとした事前処理をしてあげるのがBashなどシェルコマンドを使うコツだと思うんですが。

失われた世界の知識になりつつありますよね。

この知識を使えば、繰り返しが出てくるデータを上手く集計することができそうな気がす。

たとえば、

  • 授業の提出物ファイル(フォルダ)から、生徒が毎回提出しているか。
  • チャットルームのログから、毎週の出席者を取り出したい
  • 商品の売上データから日々の売上の有無の計算
  • 会議室の、使用履歴とかを展開したり

フォルダごとやファイルごとに同じデータを繰り返し記録していたり、出現を数えてたりそのような古の知識はUNIX哲学だったのだろうが、たぶんもう忘れられた世界。