web-dev-qa-db-ja.com

別のファイルにない1つのファイルの行を取得するツールはありますか?

ファイルAには含まれているがファイルBには含まれていない行を取得できるツールはありますか? Perlなどで簡単なスクリプトを作成することもできますが、そのようなものがすでに存在する場合は、これから時間を節約します。

111
daisy

はい。テキスト文字列をファイルから検索するための標準のgrepツールを使用すると、あるファイルのすべての行を別のファイルから差し引くことができます。

grep -F -x -v -f fileB fileA

これは、fileBの各行をパターン(-f fileB)と一致するプレーン文字列(通常の正規表現ではない)として扱います(-F)。行全体で強制的に一致させます(-x)と一致しない行のみを出力します(-v)。したがって、fileBのどの行とも同じデータを含まないfileAの行を出力します。

このソリューションの欠点は、行の順序が考慮されないことと、入力の異なる場所に重複した行がある場合、期待どおりの結果が得られない可能性があることです。その解決策は、diffなどの実際の比較ツールを使用することです。これを行うには、ファイルの行の100%にコンテキスト値を含むdiffファイルを作成し、ファイルAをファイルBに変換する場合に削除される行だけを解析します。 (このコマンドは、正しい行を取得した後に、差分フォーマットも削除することに注意してください。)

diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
162
Caleb

答えは、比較するファイルの種類と形式に大きく依存します。

比較しているファイルがソートされたテキストファイルである場合、Richard StallmanとDavide McKenzieによって作成されたGNUツール comm が呼び出され、フィルタリングを実行できます。これはcoreutilsの一部です。

次の2つのファイルがあるとします。

$ cat a
1
2
3
4
5

$ cat b
1
2
3
4
5
6

ファイルbにないファイルaの行:

$ comm <(sort a) <(sort b) -3
    6
59
A friend

から stackoverflow ...

comm -23 file1 file2

-23は、file2の行(-2)と両方に現れる行(-3)を抑制し、file1からの一意の行のみを残します。ファイルはソートする必要があります(例にあります)が、そうでない場合は、最初にパイプでソートしてください。

Manページを参照してください ここ

-1 suppress column 1 (lines unique to FILE1)
-2 suppress column 2 (lines unique to FILE2)
-3 suppress column 3 (lines that appear in both files)
35
JJS

Grepおよびcomm(sortを使用)メソッドは、大きなファイルに対してlong時間かかります。 SiegeXとghostdog74は、2つのすばらしい 2つのファイルのいずれかに固有の行を抽出するためのawkメソッド をスタックオーバーフローで共有しました:

$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2

$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
9
Miles Wolbe

ファイルが大きく、エントリにカスタムの順序がない場合、grepは時間がかかりすぎます。簡単な代替案は

sort file1 > 1 
sort file2 > 2 
diff 1 2 | grep "\>" | sed -e 's/> //'

[file2-file1の結果は画面に表示され、パイプでファイルに出力されます。]

変更><は、逆の減算になります。 rm 1 2

5
Eshel Faraggi

Vimdiffを検討することもできます。vimエディターでファイル間の違いが強調表示されます

2
simona