ITスタートアップCTOによるITエンジニアのためのブログ

Bashのcommコマンドの使い方

2つのファイルを比較し、「片方だけに存在するデータ」や「共通して含まれるデータ」を抽出する際、Bashの comm コマンドを使うと非常に効率的です。

comm コマンドをマスターすると、Excelの vlookup を使うよりも遥かに高速に、かつコマンドライン上でスマートにデータ比較ができるようになります。 本記事では、comm コマンドの概要、オプション、目的別の使い方を、出力イメージやベン図を用いて解説します。また、よく似た diff コマンドとの使い分けや、シェルスクリプトでの使用例についても触れます。

目次

  • コマンド概要
  • コマンドオプション解説
  • 目的別の使用例
    • 両方のファイルに含まれる行のみを表示
    • 最初のファイルのみに含まれる行を表示
    • 2番目のファイルのみに含まれる行を表示
    • どちらか片方にはあるが共通していない行を表示
    • 各カラムの合計数のみ知りたい場合
  • diffコマンドとの違い
  • シェルスクリプト利用例
    • エラーログの新規発生を特定する
    • 不審なIPアドレスのフィルタリング
  • まとめ

コマンド概要

comm コマンドは、ソートされた2つのファイルを行単位で比較し、以下の3つのカラムに分けて出力します。コマンド名は英語の「common(共通)」に由来しています。

コマンド形式

comm [オプション] FILE1 FILE2

出力形式(デフォルト)

出力は以下の3カラム構成になります。各カラムはタブ(Tab)で区切られます。

カラム1カラム2カラム3
FILE1にのみ存在する行FILE2にのみ存在する行両方のファイルに存在する行

出力イメージ:

$ comm a.txt b.txt
aaa           # カラム1: a.txtのみ
		bbb   # カラム3: 両方に存在
ccc           # カラム1: a.txtのみ
		ddd   # カラム3: 両方に存在
	eee       # カラム2: b.txtのみ

コマンドオプション解説

comm のオプションは、「指定したカラムを非表示にする」という考え方で使います。

  • -1: カラム1(FILE1のみ)を非表示にする
  • -2: カラム2(FILE2のみ)を非表示にする
  • -3: カラム3(共通行)を非表示にする
  • --output-delimiter=STR: カラムの区切り文字をタブ以外(スペースなど)に変更する
  • --total: 最後に各カラムの合計行数を表示する
  • --check-order: ファイルが正しくソートされているか確認する(ソートされていない場合はエラーを出す)
  • --nocheck-order: ファイルがソートされていなくても実行する(結果が不正確になる可能性があるため非推奨)

ポイント: 特定のカラムを表示したいときは、それ以外のカラム番号を指定して消すのがコツです(例:共通行だけ見たいなら -12)。

目的別の使用例

以下の2つのファイルを使って解説します。comm はファイルがソートされている必要があるため、プロセス置換 <(sort FILE) を使って実行時にソートするのが一般的です。

  • favorite.txt(好きな食べ物): クッキー, ラーメン, サラダ, 唐揚げ, チョコレート
  • healthy.txt(健康的な食べ物): 豆腐, 納豆, サラダ, わかめ

両方のファイルに含まれる行のみを表示

いわゆる 「積集合(AND)」 です。カラム1と2を非表示にします。

# Bash
# 好きで、かつ健康的な食べ物を抽出
comm -12 <(sort favorite.txt) <(sort healthy.txt)

# 出力
サラダ

ベン図の積集合:

ベン図による積集合

最初のファイルのみに含まれる行を表示

「AにはあるがBにはない」という 「差集合」 です。カラム2と3を非表示にします。

# Bash
# 好きだが、健康的ではない食べ物を抽出
comm -23 <(sort favorite.txt) <(sort healthy.txt)

# 出力
クッキー
チョコレート
ラーメン
唐揚げ

ベン図の差集合:

ベン図による差集合AマイナスB

2番目のファイルのみに含まれる行を表示

「BにはあるがAにはない」という 「差集合」 です。カラム1と3を非表示にします。

# Bash
# 健康的だが、好きではない食べ物を抽出。
comm -13 <(sort favorite.txt) <(sort healthy.txt) 

# 出力
わかめ
豆腐
納豆

ベン図で表現すると以下のようになります。

ベン図の差集合BマイナスA

どちらか片方にはあるが共通していない行を表示

いわゆる 「排他的論理和(XOR)」 です。共通のカラム3を非表示にします。 ここでは見やすくするために、tr コマンドで先頭のタブを削除します。

# Bash
# 好きだが健康的でない、または健康的だが好きではないものcomm -3 <(sort favorite.txt) <(sort healthy.txt) | tr -d '\t'

# 出力
わかめ
クッキー
チョコレート
ラーメン
唐揚げ
豆腐
納豆

ベン図の排他的論理和(XOR):

ベン図による排他的論理和

各カラムの合計数のみ知りたい場合

--total オプションを使います。全て表示すると見づらいため、結果の数値だけが必要な場合は -123 ですべてのカラムを非表示にします。

# Bash
comm -123 --total <(sort favorite.txt) <(sort healthy.txt) 

# 出力
#(FILE1のみ / FILE2のみ / 共通)
4	3	1	合計

diffコマンドとの違い

diff も差分を表示するコマンドですが、用途が異なります。

特徴commdiff
主な対象データセット、リスト、CSVの列などソースコード、設定ファイル、文章
前提条件事前ソートが必要ソート不要
出力形式3カラムのシンプルな構成行番号や変更記号(+, -)を含む
スクリプト利用パイプで繋ぎやすく非常に向いている人が見るための比較に向いている

commを使ったパイプ例:

# Bash 
# 共通していない行をクリップボードにコピー
comm -3 <(sort favorite.txt) <(sort healthy.txt)  | tr -d '\t' | xclip -selection clipboard

シェルスクリプト利用例

commはログ分析で特に便利なので、いくつか例を紹介します。

エラーログの新規発生を特定する

昨日と今日のログを比較して、今日から新しく発生するようになったエラーメッセージだけを抽出します。

# タイムスタンプ部分(1-2列目など)を削除してメッセージ部分だけで比較
comm -13 <(cut -d' ' -f3- yesterday.log | sort -u) \
         <(cut -d' ' -f3- today.log     | sort -u)
  • ユースケース: アプリのデプロイ前後で、新しいバグが出ていないか確認する場合。
  • 解説: cut -d' ' -f3- で時刻情報を切り落とし、エラー内容のみに揃えてから比較しています。-13 により「昨日にはなくて今日あるもの」だけが表示されます。

不審なIPアドレスのフィルタリング

「ホワイトリスト(許可されたIP)」と「現在のアクセスログ」を比較し、許可リストに載っていない新しいIPアドレスを抽出します。

# ログからユニークなIPを抽出し、ホワイトリストと比較
comm -23 <(awk '{print $1}' access.log | sort -u) \
          <(sort whitelist.txt)
  • ユースケース: セキュリティ監査や、DDoS攻撃の疑いがある際の調査。
  • 解説: -23 を使うことで、「現在のログ(1番目)」にあるが「ホワイトリスト(2番目)」には存在しないIPのみを表示します。

まとめ

Bashの comm コマンドは、大量のデータリストを比較する際に非常に強力です。

  • ソート済みの2ファイルを比較して3カラムで出力する。
  • -12(共通行)や -23(FILE1のみ)のように、消したいカラムを指定して使う。
  • シェルスクリプト内で、データの差分抽出や重複チェックを行うのに最適。

特にログ分析やマスタデータの照合などで力を発揮します。ぜひ日々の業務に取り入れてみてください。