集合演算っぽくファイルの足し算と引き算をする

実は僕はソフトウェアエンジニアなのです。というわけで、(たしか)初の技術ネタ。
Unixファイルシステム上に、次のようなソート済みのfile1とfile2があるとします。

$ cat file1
a
b
d
e

$ cat file2
b
c
d
f

それぞれのファイルを集合、各行を要素と見なして、Unixコマンドのみで演算をしてみる。
file1とfile2を単純に足し算(結合)する場合はこう。

$ cat file1 file2
a
b
d
e
b
c
d
f

でも、これだと全然集合っぽくない。

和集合(file1∪file2)

file1とfile2の少なくとも一方に含まれる要素を重複なしでリストする。

$ cat file1 file2 | sort | uniq
a
b
c
d
e
f

こんな書き方もできる。

$ join -a1 -a2 file1 file2
a
b
c
d
e
f

差集合(file1―file2)

file1に含まれるけど、file2には含まれない要素をリスト。

$ diff file1 file2 | awk '/^</{print $2}'
a
e

分かりづらいので、diffの出力だけを見てみる。

$ diff file1 file2
1d0
< a
2a2
> c
4c4
< e
---
> f

'd'のセクションにリストされる要素は、file1にしか含まれないという意味なので、結果集合に含まれる。
'a'のセクションはfile2にのみ含まれるので、結果集合には含まれない。
'c'のセクションはfile1のほうの要素だけが結果集合に含まれる。
要は、行頭の文字が'<'の場合に、空白以降を出力すればよい。そのフィルターをawkでやっている。

積集合(file1∩file2)

file1とfile2の両方に含まれる要素をリスト。これは意外と楽チン。

$ join file1 file2
b
d