commコマンドで、差分行の抽出

この記事では、
ファイルの行差分を抽出する、commコマンドについて紹介します。

commコマンドとは

commコマンドは、ソート済みの2つのファイルを比較して、
片方にのみ存在する行、または両方に存在する行だけを
抽出することができるコマンドです。

使い方

このコマンドは
comm [options] FILE1 FILE2
のように使います。

注意しないといけないのは、FILE1, FILE2 ともに
ソート済みでなければならないという事です。

テストデータ

今回、比較用のファイルを適当に用意しました。
ソート済みですよ!
ソートされてないファイルは正しく比較する事ができません。

FILE1

$ cat a.txt
collection
guitar
highway
month
pizza
presence
sir
situation
tennis
version

FILE2

$ cat b.txt
advice
highway
homework
independence
republic
science
sir
situation
tennis
version

出力結果

上記のファイルを比較した、出力結果はわかりやすく
FILE1にのみ存在する行 ー FILE2にのみ存在する行 ー 両方に存在する行
という、タブで列わけされた形で出力されます。

$ comm a.txt b.txt
    advice
collection
guitar
        highway
    homework
    independence
month
pizza
presence
    republic
    science
        sir
        situation
        tennis
        version
  • 1列目が、FILE1 (a.txt) にのみ存在する行
  • 2列目が、FILE2 (b.txt) にのみ存在する行
  • 3列目が、両ファイルに存在する行

ソートして比較 (プロセス置換を利用した例)

もし、ファイルがまだソートされていない場合、
プロセス置換を利用して、ソート済みにして渡す方法もあります。

$ comm <(sort a.txt) <(sort b.txt)

- を使って標準入力を利用する例

ファイルを指定する代わりに、
-を渡すと標準入力の内容と比較する事もできます。

$ cat a.txt | comm - b.txt

a.txtを標準入力から受け取っていますが、
もとの例と同じ、出力結果が得られます。

なにか基準になるファイルと、
処理結果を比較したい場合などに便利でしょう。

マニュアル

commコマンドのマニュアル

$ man comm
SYNOPSIS
     comm [-123i] file1 file2

DESCRIPTION
     The comm utility reads file1 and file2, which should be sorted lexically, and produces three text columns as output: lines only in file1; lines only in
     file2; and lines in both files.

     The filename ``-'' means the standard input.

     The following options are available:

     -1      Suppress printing of column 1.

     -2      Suppress printing of column 2.

     -3      Suppress printing of column 3.

     -i      Case insensitive comparison of lines.

     Each column will have a number of tab characters prepended to it equal to the number of lower numbered columns that are being printed.  For example, if col-
     umn number two is being suppressed, lines printed in column number one will not have any tabs preceding them, and lines printed in column number three will
     have one.

     The comm utility assumes that the files are lexically sorted; all characters participate in line comparisons.

Suppress オプション

commコマンドには、-1, -2, -3 というオプションが指定できます。
これらは、指定した数字の列が出力されないようにするもの、
抑制(Suppress)するオプションです。

  • -1 FILE1にのみ存在する行を出力しない
  • -2 FILE2にのみ存在する行を出力しない
  • -3 両方に存在する行を出力しない

しかも、このオプションは組み合わせて利用することができます。

Suppress オプションの組み合わせで抽出

FILE1 にのみ存在する行

-23 FILE1 にのみ存在する行を出力する。

FILE2にのみ存在する行は出力しない
両方に存在する行は出力しない

$ comm -23  a.txt b.txt
collection
guitar
month
pizza
presence

FILE2 にのみ存在する行

-13 FILE2 にのみ存在する行を出力する。

FILE1にのみ存在する行は出力しない
両方に存在する行は出力しない

$ comm -13  a.txt b.txt
advice
homework
independence
republic
science

両方に存在する行

-12 両方に存在する行を出力する。

FILE1にのみ存在する行は出力しない
FILE2にのみ存在する行は出力しない

$ comm -12  a.txt b.txt
highway
sir
situation
tennis
version

check-order オプション 

MacOSにデフォルトで入っているcommコマンドでは、
このオプション使えないようですが、

CentOSなどのLinuxにインストールされている方であれば、
これらのオプションが使えます。

  • --check-order
    指定のファイルが、ソート済みかチェックして、エラー出力する。

  • --nocheck-order
    ソートチェックはしない。
    しかし正しく比較動作しているかは不明。

output-delimiter オプション

こちらも、MacOSにデフォルトで入ってるものでは、使えないようです。

--output-delimiter=STR
列を区切る文字列を指定する事ができます。(デフォルトはTAB)

まとめ

  • ソート済みファイルから、
    片方にだけ存在する行両方に存在する行を抽出可能。

  • 比較ファイルは、ソートしておく必要がある。
    (プロセス置換を利用するのもアリ)

  • Suppress オプションを組み合わせて、抽出できる。

  • nocheck-order オプションもあるが、ちゃんと比較動作するかは不明

  • output-delimiter オプションで、区切り文字を指定可能

  • - で、ファイルの代わりに標準入力を利用可能

コメントを残す