* nix: выполнить объединение / пересечение / различие списков - PullRequest
12 голосов
/ 15 декабря 2011

Мне иногда нужно сравнить два текстовых файла. Очевидно, diff показывает различия, а также скрывает сходства, что является своего рода точкой.

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

Существуют ли такие же простые общие утилиты или однострочные, которые могут это сделать?


Примеры:

a.txt

john
mary

b.txt

adam
john

$> set_union a.txt b.txt
john
mary
adam

$> set_intersection a.txt b.txt
john

$> set_difference a.txt b.txt
mary

Ответы [ 4 ]

19 голосов
/ 15 декабря 2011

Объединение: sort -u файлы ...

Пересечение: sort файлы ... | uniq -d

Разница: sort файлы ... | uniq -u

7 голосов
/ 15 декабря 2011

Если вы хотите получить общие строки между двумя файлами, вы можете использовать утилиту comm .

A.txt:

A
B
C

b.txt

A
B
D

и затем использование comm даст вам:

$ comm <(sort A.txt) <(sort B.txt)
        A
        B
C
    D

В первом столбце у вас есть то, что находится в первом файле, а не во втором.

Во втором столбце у вас есть то, что находится во втором файле, а не в первом.

В третьем столбце у вас есть то, что находится в обоих файлах.

0 голосов
/ 08 сентября 2016

Я не могу комментировать ответ Аарона Дигуллы, который, несмотря на то, что он принят, на самом деле не вычисляет разность установок .

Заданная разница A \ B с заданными входами должна возвращать только mary, но принятый ответ также неверно возвращает adam.

Этот ответ имеетawk однострочник, который правильно вычисляет установленную разницу:

awk 'FNR==NR {a[$0]++; next} !a[$0]' b.txt a.txt
0 голосов
/ 15 декабря 2011

Если вы не возражаете против использования небольшого количества Perl, и если ваши размеры файлов разумны, так что они могут быть записаны в хеш, вы можете собрать файлы в два хеша:

#...get common keys in an array...
my @both_things
for (keys %from_1) {
    push @both_things, $_ if exists $from_2{$_};
}

#...put unique things in an array...
my @once_only
for (keys %from_1) {
    push @once_only, $_ unless exists $from_2($_);
}
...