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だけで頑張るよりだいぶ速かった。