2つの大きなファイルの違い

2つの大きなファイルの違い

「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 -qdiff -sうまくいきませんでした。順序は重要ではありません。重要なのは、> や < や空白なしで、違いだけを確認したいということです。

grep -FvF小さなファイルではうまくいきましたが、大きなファイルではうまくいきませんでした。

最初のファイルには 500 万行以上が含まれ、2 番目のファイルには 1300 行が含まれます。

したがって、results.csv は約 4,998,700 行になります。

私も試してみましたgrep -F -x -v -f が、うまくいきませんでした。

答え1

次のような仕事に向いているようです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

答え2

プロセス置換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

またはオリは提案したコマンドのグループ化も使用できます。

$ { 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

答え3

行の順序が関係ない場合は、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 はこれらの共通行に一致しない行を検索します。

答え4

順序を維持する必要がないので、次のようにします。

sort test1.csv test2.csv | uniq -u
  • sort test1.csv test2.csv: マージとソートを行いtest1.csvtest2.csv
  • uniq -u: 重複のない行のみを出力します

関連情報