Linuxで2つのファイルの共通行を出力する

機会があったので、調べてみました。
2ファイルの差分はdiffコマンドで取るけど、その逆の共通している部分はどうやって取得するのか。エレガントなやり方はやっぱりgrepコマンドを使うのかしら?

前提

$ diff -c5 {a,b}.txt
*** a.txt	2013-08-28 18:54:49.293055071 +0900
--- b.txt	2013-08-28 18:53:58.517693404 +0900
***************
*** 1,6 ****
  1
- 2
  3
  5
  5
  6
--- 1,6 ----
  1
  3
+ 4
  5
  5
  6

こういう2つのファイルがあったとして・・・

grepで

$ grep -x -f {a,b}.txt
1
3
5
5
6

grepコマンドの"-x"オプションを使うと、こんな感じで、2ファイルの共通部分が出力される。

-x, --line-regexp
パターンが行全体とぴったりマッチしたときにのみ、その行を選択します。 (-x オプションは POSIX で規定されています)

Man page of GREP


通常であれば、共通部分なので、これで事足りると思うけど、↑のケースだと、場合によっては連続するような5の重複をなくしたいってケースもあるかもしれないので、そういう時は、uniqコマンドでもかましておけばOKなのかな。

$ grep -x -f {a,b}.txt | uniq
1
3
5
6

番外(sortとuniqで)

uniqコマンド使うところで思い出したけど、sortコマンドとuniqコマンド組み合わせても出来そう。
ただし、↓のように、"sort"してから"uniq -d"使う以上、全ての行で重複する文字列とかも、1つ(uniq)になって出てしまう。

$ sort {a,b}.txt | uniq -d
1
3
5
6

こんな感じで、sortコマンドで並べ替えてから、uniqコマンドの"-d"オプションで絞り込む。

-d, --repeated
同じ内容が 2 行以上あるものだけを出力する。

Man page of UNIQ


ここまで来ると、違いをしっかり把握すべく、grepのソースコード読んだほうが良さそうだ。・・・が、時間の都合上、一旦To Be Continuedな感じで...(また今度)

それでは!=͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́

追記(commで)

commコマンドでも出来ることを教えてもらいました。

comm - それぞれソートされた二つのファイルを行ごとに比較する

Man page of COMM

2ファイルがソート済みの前提ではありますが、↑の例の2ファイル(既にソートされている)だと以下のような結果になりました。

$ comm -1 -2 {a,b}.txt
1
3
5
5
6