「test1.csv」があります
200,400,600,800
100,300,500,700
50,25,125,310
およびtest2.csvとそれが含まれています
100,4,2,1,7
200,400,600,800
21,22,23,24,25
50,25,125,310
50,25,700,5
今
diff test2.csv test1.csv > result.csv
とは異なります
diff test1.csv test2.csv > result.csv
どちらが正しい順序なのかわかりませんが、何か他のものが必要です。上のコマンドは両方とも次のようなものを出力します
2 > 100,4,2,1,7
3 2,3c3,5
4 < 100,300,500,700
5 < 50,25,125,310
6 \ No newline at end of file
7 ---
8 > 21,22,23,24,25
9 > 50,25,125,310
差のみを出力したいので、results.csvは次のようになります。
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
diff -q
とdiff -s
を試しましたが、彼らはトリックをしませんでした。順序は関係ありません。重要なのは、違いだけを見たいということです。
grep -FvF
は大きなファイルではなく小さなファイルでトリックを行いました
最初のファイルには500万行以上が含まれ、2番目のファイルには1300行が含まれています。
そのため、results.csvは〜4,998,700行になるはずです。
grep -F -x -v -f
も試しましたが、うまくいきませんでした。
comm
の仕事のように聞こえます:
$ comm -3 <(sort test1.csv) <(sort test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
man comm
で説明されているように:
-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)
したがって、-3
は、ファイルの1つに固有の行のみが印刷されることを意味します。ただし、それらは見つかったファイルに応じてインデントされます。タブを削除するには、次を使用します。
$ comm -3 <(sort test1.csv) <(sort test2.csv) | tr -d '\t'
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
この場合、ファイルを並べ替える必要さえありません。上記を単純化して次のことができます。
comm -3 test1.csv test2.csv | tr -d '\t' > difference.csv
grep
プロセス置換でbash
を使用:
$ cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
出力をresults.csv
として保存するには:
cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv) >results.csv
<()
は bash
プロセス置換パターン
grep -vFf test2.csv test1.csv
は、test1.csv
のみに固有の行を検索します
grep -vFf test1.csv test2.csv
は、test2.csv
のみに固有の行を検索します
最後に、cat
によって結果を要約します
または Oli推奨 のように、コマンドのグループ化も使用できます。
$ { grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv; }
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
または、次々に実行します。どちらもSTDOUTに書き込み中なので、最終的に追加されます。
$ grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
diff
の--*-line-format=...
オプションを使用しますdiff
必要なものを正確に伝えることができます-以下で説明します:
diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' f1.txt f2.txt
printf
数値形式と同様に、diffの出力を非常に詳細な方法で指定することができます。
最初のファイルtest1.csv
の行は「古い」行と呼ばれ、2番目のファイルtest2.csv
の行は「新しい」行と呼ばれます。これは、diff
を使用してファイルの変更内容を確認する場合に意味があります。
必要なオプションは、「古い」行、「新しい」行、および「変更されていない」行の形式を設定するためのものです。
必要なフォーマットは非常にシンプルです:
変更された行(新旧)については、行のテキストのみを出力します。 %L
は、行テキストの形式記号です。
変更されていない行については、何も表示しません。
これにより、サンプルデータを使用して、--old-line-format='%L'
などのオプションを記述し、すべてをまとめることができます。
$ diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' test1.csv test2.csv
100,4,2,1,7
100,300,500,700
21,22,23,24,25
50,25,700,5
ファイルのサイズは異なるため、重要でない場合は入力ファイルを交換してみてください。diff
の内部動作が一方よりも他方をうまく処理できる可能性があります。より良いのは、必要なメモリが少ないか、計算が少ないことです。
大きなファイルでdiff
を使用するための最適化オプションがあります:--speed-large-files
。ファイル構造に関する仮定を使用しているので、それがあなたのケースに役立つかどうかは明確ではありませんが、試してみる価値はあります。
形式オプションについては、man diff
の下の --LTYPE-line-format=LFMT
で説明しています。
行の順序が関係ない場合は、awk
またはPerl
を使用します。
awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv
grep
を使用して、共通行を取得し、それらを除外します。
grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv
内部grepは共通行を取得し、外部grepはこれらの共通行と一致しない行を検出します。
順序を保持する必要はないので、単純に:
sort test1.csv test2.csv | uniq -u
sort test1.csv test2.csv
:test1.csv
とtest2.csv
のマージと並べ替えuniq -u
:重複のない行のみを出力します