Разница двух больших файлов

Разница двух больших файлов

У меня есть "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сработало с файлами меньшего размера, но не с большими

Первый файл содержит более 5 миллионов строк, второй файл содержит 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означает, что будут напечатаны только строки, уникальные для одного из файлов. Однако они имеют отступ в соответствии с тем, в каком файле они были найдены. Чтобы удалить вкладку, используйте:

$ 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.csvиtest2.csv
  • uniq -u: печатает только те строки, которые не имеют дубликатов

Связанный контент