Удаление строк, общих для выходных данных двух команд

Удаление строк, общих для выходных данных двух команд

Допустим, у меня есть две команды, которые возвращают какой-то текст. Например:

$ ./c1
/usr/bin/foo
/usr/bin/bar
/usr/bin/baz
$ ./c2
/usr/bin/foo
/usr/bin/qux
/usr/bin/buzz
/usr/bin/bar

Я хочу удалить дубликаты строк; т.е. вывод будет таким (порядок не важен):

/usr/bin/baz
/usr/bin/qux
/usr/bin/buzz

Как бы я это сделал?

решение1

Достаточно простой конвейер должен справиться с этой задачей:

(./c1; ./c2) | sort -u

Скобки получают stdout обоих ./c1и ./c2stdin команды sort. Опция -uпечатает только 1 из каждой группы совпадающих строк.

Спасибо Джону У. Х. Смиту за то, что он заметил упрощение, и Бакуриу за понимание.

решение2

С commиз GNU coreutils:

$ comm -3 <(sort -u <(./c1)) <(sort -u <(./c2)) | tr -d '\t'
/usr/bin/baz
/usr/bin/buzz
/usr/bin/qux

От man comm:

Compare sorted files FILE1 and FILE2 line by line.

       With  no  options,  produce  three-column  output.  Column one contains
       lines unique to FILE1, column two contains lines unique to  FILE2,  and
       column three contains lines common to both files.

       -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

awk-pipe, чтобы пропустить только первое вхождение входной строки:

( ./c1 ; ./c2 ) | awk '!u[$0]++'

Это не требует времени на сортировку, но требует памяти увиденных строк. Так что для больших объемов ввода sortи uniqможет быть лучше...

решение4

Я бы рекомендовал использовать sedдля разбора текста и удаления дубликатов строк. Так что первая команда сохраняет дубликаты строк sed '$!N; /^\(.*\)\n\1$/!P; D'

Вторая команда удалит дубликаты. sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

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