Saída as linhas comuns (semelhanças) de dois arquivos de texto (o oposto de diff)?

21

Diff é uma ótima ferramenta para exibir as alterações entre dois arquivos. Mas como exibir as semelhanças de dois arquivos de texto (ignorando as diferenças)?

Ou seja, entrada de amostra:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Pseudo saída (algo como isto):

@@ 2,3
=Hello World

Apenas classificar os dois arquivos e usar comm não é suficiente, porque nesse caso as informações da linha são perdidas.

maxschlepzig
fonte

Respostas:

24

Que tal usar diff, mesmo que você não queira uma diff? Tente o seguinte:

diff --unchanged-group-format='@@ %dn,%df 
  %<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt

Aqui está o que recebo com seus dados de amostra:

$ cat a.txt 
Foo Bar
X
Hello
World
42
$ cat b.txt 
Foo Baz
Hello
World
23
$ diff --unchanged-group-format='@@ %dn,%df
%<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt
@@ 2,3
Hello
World
Mike Gray
fonte
2
Você pode evitar a incorporação de uma nova linha literal como esta:...%df'$'\n''%<'...
Pausada até novo aviso.
1
Você também pode fazer o seguinte: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(Observe as aspas duplas.)
Pausado até novo aviso.
Coisas boas! Eu não sabia que estas opções, porque eu só olhei para a página homem diff ...
maxschlepzig
Estou usando diff --version diff (GNU diffutils) 2.8.1 E recebo o seguinte erro: diff: opções conflitantes de estilo de saída diff: Tente `diff --help 'para obter mais informações.
Sujay
Eu estava recebendo "error: diff: opções conflitantes de estilo de saída diff" porque eu tinha um alias de diff definido. Use which diffpara ver se este é o seu problema.
justinjhendrick
14
grep -Fxf file1 file2

-Fsignifica combinar strings simples (não regexps), -xsignifica apenas correspondências de linha inteira, -fsignifica pegar 'padrões' (ou seja, linhas) do arquivo nomeado como argumento

tobyodavies
fonte
3
Não são -fe são -Ftrocados? Pelo menos na minha grepversão é assim. Eu preciso fornecer file2entrada para o -fargumento, como cat file1 | grep -Fxf file2, e depois funciona.
Birei
Isso não funcionou para mim.
Chaminda Bandara
7

commpode ser usado. man commpara todas as opções, mas convém usar comm -12 ...para mostrar apenas as linhas existentes nas duas entradas.

Como as pessoas apontaram, você precisa passar sua opinião sortprimeiro.

Oli
fonte
1
Hum, isso funciona apenas para linhas comuns que estão no mesmo número de linha nos dois arquivos.
maxschlepzig
2
comm parece ser apenas para arquivos classificados e não fornece essa saída útil para o caso de uso do OP. Seu exemplo: $ comm -12 ab Olá Mundo comm: file 1 não está na comm ordem de classificação: Arquivo 2 não está na ordem de classificação
Marcel Stimberg
@maxschlepzig: você deve classificar seus arquivos antes de passá-los para o comm.
Hemant
2
Ao classificar, você se livra de todas as informações sobre a posição das linhas comuns. Você também não classificaria os arquivos antes de compará-los com o diff.
Marcel Stimberg
7

Eu não acho que exista um único comando que faça o que você deseja que ele faça. Você pode tentar combinar a saída de diffcom grep, no entanto. Se os seus arquivos de texto contêm nenhum dos personagens |, <, >, o seguinte lhe dá saída um pouco útil:

$ diff --side-by-side a b | grep -n -v "[|<>]"
3:Hello                             Hello
4:World                             World
Marcel Stimberg
fonte
Tente o seguinte:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
Pausado até novo aviso.
isso parece melhor - mas você deve incluir <e> no grep para se livrar também das linhas adicionadas em qualquer arquivo.
Marcel Stimberg
2

Dick Grune escreveu uma família de ferramentas para esse tipo de coisa:

http://dickgrune.com/Programs/similarity_tester/

Existem versões que analisam a sintaxe de vários idiomas, para que coisas como variáveis ​​renomeadas possam ser vistas como inalteradas.

É empacotado como similarity-testerno Debian e Ubuntu.

Douglas Bagnall
fonte