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

Вы также можете использовать gpasswd:

sudo gpasswd -d username sudo

Это приведет к удалению username из группы sudo.

1
задан 24 June 2015 в 01:27

4 ответа

Использование 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
6
ответ дан 23 May 2018 в 19:33
  • 1
    Почему cat две перенаправленные команды? Почему бы просто не запустить один, а затем другой? grep ... ; grep ... или { grep ... ; grep ... ; }, если вы хотите что-то сделать с коллективным выходом. – Oli♦ 24 June 2015 в 00:54
  • 2
    @Oli Спасибо .. это отличная идея .. я не думал об этом .. – heemayl 24 June 2015 в 01:01

Если порядок строк не имеет значения, используйте awk или perl:

awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv

Используйте grep, чтобы получить общие линии и отфильтровать эти строки out:

grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv

Внутренний grep получает общие строки, тогда внешняя grep находит строки, которые не соответствуют этим общим строкам.

4
ответ дан 23 May 2018 в 19:33
  • 1
    Ваша команда awk просто повторно реализует sort | uniq -u, что дает неверный ответ, когда один файл содержит повторяющиеся строки. Для grep я бы сказал «внутренний» / «внешний», а не «внутренний» / «внешний». – Peter Cordes 24 June 2015 в 18:49
  • 2
    @PeterCordes да, это так, и кто вы скажете, что это неправильный результат? – muru 24 June 2015 в 21:07
  • 3
    Неправильно в том смысле, что это не совсем то, о чём задавался этот вопрос в этом случае. Это может быть то, что кто-то хочет, но вы должны указать разницу между тем, что будет напечатан ваш awk, и что будут печатать ответы comm -3 и diff. – Peter Cordes 24 June 2015 в 21:13
  • 4
    @PeterCordes снова, кто вы это скажете? Пока OP не говорит, что это то, чего они хотят, мне все равно, отличается ли выход от функции comm -3. Я не вижу причин, почему I должен это объяснить. Если вы хотите редактировать заметку, не стесняйтесь. – muru 24 June 2015 в 21:15
  • 5
    ОП сказал, что хочет разницы. Это не всегда то, что твоя программа производит. Программа, которая производит один и тот же вывод для одного тестового файла, но не удовлетворяющая описанию, написанному для всех случаев, требует нажатия клавиш вверх. Я здесь, чтобы сказать это, и это правда, независимо от того, кто я или кто вы. Я добавил примечание. – Peter Cordes 24 June 2015 в 21:23

Используйте опции --*-line-format=... для diff

Вы можете точно указать diff именно то, что вам нужно - ниже:

diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' f1.txt f2.txt

Можно указать вывод diff в очень подробном виде, подобно формату номера printf.

Строки из первого файла test1.csv называются «старыми» строками, а строки второго, [ f8], являются «новыми» строками. Это имеет смысл, когда 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
[d9 ]

Замечания о производительности

Поскольку файлы имеют разный размер, попробуйте обмениваться входными файлами, если это не имеет значения, может быть, что внутренний работы diff могут обрабатывать один путь лучше другого. Лучше либо меньше памяти, либо меньше вычислений.

Существует опция оптимизации для использования diff с большими файлами: --speed-large-files. Он использует предположения о структуре файла, поэтому неясно, помогает ли это в вашем случае, но стоит попробовать.

Параметры формата описаны в man diff в разделе --LTYPE-line-format=LFMT.

4
ответ дан 23 May 2018 в 19:33

Поскольку порядок не нужно сохранять, просто:

sort test1.csv test2.csv | uniq -u
sort test1.csv test2.csv: слияния и сортировки test1.csv и test2.csv uniq -u: печатает только строки, которые имеют нет дубликатов
3
ответ дан 23 May 2018 в 19:33
  • 1
    Это не работает, если один файл содержит строку два раза, что не отображается в другом файле. Оба входа будут в diff результате. – Volker Siegel 24 June 2015 в 10:04

Другие вопросы по тегам:

Похожие вопросы: