メモの日々


2017年01月11日(水) [長年日記]

[unix][howto] ファイル同士のの引き算

ファイルAには存在するがファイルBには存在しない行を知りたいことがあった。どうするのがいいのだろう。

grepで頑張る

% grep -v -F -x -f B A

とすれば目的を達せられる感じ。オプションの意味をJMから引用。

-v, --invert-match

マッチの意味を逆にして、マッチしない行を抜き出して表示します。 (-v オプションは POSIX で規定されています)

-F, --fixed-strings

PATTERN を改行で区切られた固定文字列 (訳注: すなわち、正規表現ではない ただの文字列) のリストとして扱い、 その文字列のどれかとマッチするかを調べます。 (-F オプションは POSIX で規定されています)

-x, --line-regexp

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

-f FILE, --file=FILE

パターンを FILE から 1 行 1 パターンとして読み込みます。 空のファイルはパターンを含まないので、何にもマッチしません。 (-f オプションは POSIX で規定されています)

簡単な例。

% cat A
pen
pineapple
apple
pen

% cat B
apple
google

% grep -v -F -x -f B A
pen
pineapple
pen

diffで頑張る

行の順番が入れ替わってもよければdiff(とsortとgrep)を使う手もありそう。

% diff -u <(sort A) <(sort B) | grep '^-'
--- /dev/fd/63  2017-01-11 19:02:44.127377698 +0900
-pen
-pen
-pineapple

余計な行や行頭文字が付いてしまうけれど。場合に依るだろうけど、試したケース(AとBが大きなファイルの場合)ではこちらの方がgrepだけで頑張るよりだいぶ速かった。