あるファイルの行を別のファイルにないようにするツールはありますか?


110

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


stackoverflow.com/questions/5812756/…」を参照してください
harish.venkat

回答:


159

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

grep -F -x -v -f fileB fileA

これは、fileBの各行をパターン(-f fileB)として使用し、一致する(通常の正規表現ではなく)プレーンストリングとして処理することで機能します(-F)。行全体で一致を強制的に発生させ(-x)、一致しない行のみを出力します(-v)。したがって、fileBの行と同じデータを含まないfileAの行を印刷しています。

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

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

@ inderpreet99小文字の-u引数は、スペースが後に続かない限り、実際には数値のパラメーターを取ります。以前の方法の利点は、値の有無にかかわらず動作するため、出力ではなく返されたサブコマンドルーチンで何かを使用できることです。一方、大文字の「-U」には引数が必要です。
カレブ

注意してください、grep -fはO(N ^ 2)であると思います:stackoverflow.com/questions/4780203/…–
rogerdpack

1
diffパイプラインは、治療のおかげで動作します。
フェリペアルバレス

ソートの問題に対処するために、コマンドでプロセス置換を使用してgrep、必要に応じて各ファイルを処理することができます。例:grep -F -x -v -f <(sort fileB) <(sort fileA)
トニーセザロ

@TonyCesaroデータセットが順序固有ではなく、重複を考慮する必要がない場合に機能します。使用する利点はdiff、ファイル内の位置が考慮されることです。
カレブ

57

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

比較しているファイルがソートされたテキストファイルである場合、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

1
言及するcomm場合は+1 。残念ながら、commソートされたファイルが必要です
-Arcege

11
並べ替えますか?comm <(sort a)<(sort b)-1 -2
Sirex

これは奇妙な構文です。<()?それは動作し、私はそれを取得しますが、この奇妙さの名前はありますか?
-mlissner

2
@mlissner <()は、プロセス置換としても知られています
ミク

1
comm元々1973年頃、rmsではなく、Bell Labsの誰かによって書かれました。あなたはずっと後に来たGNU実装について言及しています。ここ数年、Unixユーティリティのさまざまな実装が行われてきました。
ステファンシャゼラス

32

stackoverflowから...

comm -23 file1 file2

-23は、両方のファイル、またはファイル2のみにある行を抑制します。ファイルはソートする必要があります(これらは例にあります)。

こちらのmanページをご覧ください


これは...何らかの理由で、私のために動作しません

@Janはファイルがソートされていますか?どのように並べ替えましたか?
JJS

8

grepおよびcomm(with with sort)メソッドは、大きなファイルで長い時間がかかります。SiegeXとghostdog74は、Stack Overflowの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

2
巨大なファイルを使用してこれを行う場合、巨大なファイルを連想配列にロードする際のメモリの制約は非常に高くなります。
チャールズダフィー

4

ファイルが大きく、エントリにカスタムオーダーがない場合、grepにかかる時間が長すぎます。簡単な代替手段は

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

[file2-file1の結果は画面に表示され、パイプでファイルに送信されるなど]

に変更>する<と、反対の減算が行われます。rm 1 2


2

また、vimdiffを検討することもできます。vimdiffは、vimエディターのファイル間の違いを強調表示します


1
しかし、Vimdiffで自動的に減算を行う簡単な方法はありますか?
カザーク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.