Removendo linhas comuns às saídas produzidas por dois comandos

Removendo linhas comuns às saídas produzidas por dois comandos

Diga, tenho dois comandos que retornam algum texto. Por exemplo:

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

Quero remover as linhas duplicadas; ou seja, a saída será (a ordem não é importante):

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

Como eu faria isso?

Responder1

Um pipeline bastante simples deve resolver o problema:

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

Os parênteses vão para stdout de ambos ./c1e ./c2para stdin do sortcomando. A opção -uimprime apenas 1 de cada grupo de linhas correspondentes.

Obrigado a John WH Smith por notar uma simplificação e a Bakuriu pela visão.

Responder2

Com commde GNU coreutils:

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

De 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)

Responder3

awk-pipe para deixar passar apenas a primeira ocorrência de uma linha de entrada:

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

Isso não leva tempo para classificar, mas precisa de uma memória das linhas vistas. Portanto, para grandes quantidades de informações sorte uniqpode ser melhor ...

Responder4

Eu recomendaria utilizar sedpara analisar o texto e remover linhas duplicadas. Então o primeiro comando mantém a linha duplicada sed '$!N; /^\(.*\)\n\1$/!P; D'

O segundo comando irá deletar as duplicatas sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

informação relacionada