O resultado de dois arquivos diff com linhas comutadas diz que falta a mesma linha duas vezes

28

Eu estou tentando entender o comando linux diff em dois arquivos cujas linhas são apenas permutação uma da outra, mas não são capazes de grok a saída que ele gera. Considere os três comandos abaixo:

[myPrompt]$ cat file1
apples
oranges
[myPrompt]$ cat file2 
oranges
apples
[myPrompt]$ diff file1 file2
1d0
< apples
2a2
> apples

Alguém pode explicar a saída enigmática acima do diff.

  1. Por que não há menção a "laranjas" na saída?
  2. O que significa 1d0e 2a2significa?

Entendo a partir desta resposta que:

"<" significa que a linha está ausente no arquivo2 e ">" significa que a linha está ausente no arquivo1

MAS isso não explica por que faltam laranjas na saída.

Nerd
fonte
12
Como orangesé a maior parte comum entre os dois arquivos, o que você obtém é a maneira mais curta de expressar as diferenças entre os dois.
Stéphane Chazelas
10
E se você quiser uma saída mais legível, basta usar diff -u file1 file2. Isso é chamado de formato "diff unificado". O formato do diff original foi criado para ser muito compacto, mas os diffs unificados devem ser muito mais legíveis.
godlygeek
4
@godlygeek Oudiff -y file1 file2
user80551

Respostas:

27

Para entender o relatório, lembre-se de que diffé prescritivo, descrevendo quais alterações precisam ser feitas no primeiro arquivo ( file1) para torná-lo igual ao segundo arquivo ( file2).

Especificamente, os dem 1d0meio eliminar eo ade 2a2meios adicionar .

Portanto:

  • 1d0significa que a linha 1 deve ser excluída em file1( apples). 0na 1d0linha 0 significa que eles teriam aparecido no segundo arquivo ( file2) se não tivessem sido excluídos. Isso significa que, ao mudar file2para file1(para trás), acrescente a linha 1 da file1linha 0 após file2.
  • 2a2significa acrescentar a segunda linha ( oranges) da file2agora segunda linha de file1(após excluir a primeira linha file1, orangesalternada para a linha 1)
caos
fonte
o que está 0dentro 1d0?
25414 Geek
@Geek see my edit
caos
1
@Geek Mas cuidado, que pode fazer nós no cérebro =)
caos
que tem, na verdade, começou a fazer nós :-)
Totó
13

Considere estes arquivos:

file1:

# cat file1
apples
pears
oranges
peaches

file2:

# cat file2
oranges
apples
peaches
ananas
banana

Como difffunciona, dado que é baseado em pedidos:

  1. difflê o primeiro bloco de linhas de file1e file2, e tenta encontrar linhas iguais:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      -------------------------------
    ->oranges    ->oranges
      peaches      apples
                   peaches
                   ananas
                   banana
    
  2. Agora ele pulará todas as linhas iguais nos dois arquivos, o que é exatamente orangeso caso:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
      -------------------------------
    ->peaches    ->apples
                   peaches
                   ananas
                   banana
    
  3. Agora encontre outro conjunto de linhas semelhantes e imprima diferenças:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      -------------------------------
    ->peaches    ->peaches
                   ananas
                   banana
    
  4. Ignore as linhas semelhantes

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      peaches      peaches
      -------------------------------
    ->           ->ananas
                   banana
    
  5. Encontre linhas idênticas, se possível, e imprima diferenças:

    line_file1    file1    line_file2    file2        differences on left (<) or right side (>)
             1    apples                              <apples 
             2    pears                               <pears 
             3    oranges           1    oranges
                                    2    apples       >apples
             4    peaches           3    peaches
                                    4    ananas       >ananas
                                    5    banana       >banana
             -----------------------------------------------
    

Agora, se eu fizer diff file1 file2:

# diff file1 file2
1,2d0
< apples
< pears
3a2
> apples
4a4,5
> ananas
> banana

Agora é simples explicar o que diffsignifica saída:

Para fazer file1igual a file2:

  • 1,2d0: Eliminar ( d) linhas 1-2de file1e modificar linha 0de file2conformidade
  • 3a2: Anexar ( a) à linha 3da file1linha 2defile2
  • 4a4,5: Anexar à linha 4de file1linhas 4-5defile2

diffcompara file1com file2linha por linha e resolve diferenças na memória temporária. Depois de file1 igualar file2 até a primeira ocorrência de uma linha file1, o que também ocorre file2, todas as linhas iguais até uma diferença não são mencionadas, geralmente indicadas como ---. Nesse caso, há apenas uma linha semelhante, que é oranges. Note que eu disse file1igual a file2, então file1é visualizado em relação file2e não o contrário.

A saída é em relação ao primeiro arquivo fornecido, neste caso file1.

polym
fonte
2
Não gosto da explicação inicial: applesocorre nos dois arquivos também.
OR Mapper
1
@ORMapper mudei a explicação. Parece mais claro / melhor agora :)?
polym 25/07
Não exatamente, por enquanto você escreveu "existe apenas uma linha semelhante, que é oranges". Errado: Na verdade, existem duas linhas, que não são apenas semelhantes , mas absolutamente idênticas . Um deles lê oranges, o outro lê apples. Além disso, sua explicação (puramente baseada em ordem) está em contradição com o comentário de Stéphane sobre a questão (baseada em comprimento) - quem está correto?
OR Mapper
@ORMapper Você esqueceu "Neste caso" e as linhas anteriores. Eu quis dizer que nesta etapa existe apenas uma linha semelhante. Vou apenas adicionar um exemplo à minha resposta para que ela possa ser melhor entendida.
polym 25/07
1
@ORMapper Além disso, você pode me dar um exemplo que mostre que a resposta baseada no comprimento está correta?
polym 25/07
8

Ali estão eles:

$ diff file1 file2
1d0
< apples
2a2
> apples
$ diff file2 file1
1d0
< oranges
2a2
> oranges
user78677
fonte
8

O formato de saída padrão (antigo) exibirá a diferença entre os arquivos sem o texto ao redor das áreas em que os arquivos diferem.

Por exemplo: 1d0 <(excluir) significa que as maçãs precisam ser removidas da 1ª linha de file1e 2a2 >(anexar) significa que as maçãs precisam ser adicionadas file2na 2ª linha, para que os dois arquivos possam ser correspondidos.

A documentação disponível em info diffexplica ainda mais:

Mostrando diferenças sem contexto

O diffformato de saída "normal" mostra cada pedaço de diferenças sem nenhum contexto circundante. Às vezes, essa saída é a maneira mais clara de ver como as linhas mudaram, sem a confusão de linhas inalteradas próximas (embora você possa obter resultados semelhantes com o contexto ou com os formatos unificados usando 0 linhas de contexto). No entanto, esse formato não é mais amplamente usado para enviar patches; para esse fim, o formato de contexto e o formato unificado são superiores. Formato normal é o padrão para compatibilidade com versões mais antigas diffe com o padrão POSIX. Use a --normalopção para selecionar este formato de saída explicitamente.

Descrição detalhada do formato normal

O formato de saída normal consiste em um ou mais pedaços de diferenças; cada pedaço mostra uma área em que os arquivos diferem. Pedaços de formato normal ficam assim:

 CHANGE-COMMAND
 < FROM-FILE-LINE
 < FROM-FILE-LINE...
 ---
 > TO-FILE-LINE
 > TO-FILE-LINE...

Existem três tipos de comandos de alteração. Cada um consiste em um número de linha ou intervalo de linhas separado por vírgula no primeiro arquivo, um único caractere indicando o tipo de alteração a ser feito e um número de linha ou intervalo de linhas separado por vírgula no segundo arquivo. Todos os números de linha são os números de linha originais em cada arquivo. Os tipos de comandos de alteração são:

LaR Adicione as linhas no intervalo R do segundo arquivo após a linha L do primeiro arquivo. Por exemplo, 8a12,15significa acrescentar as linhas 12 a 15 do arquivo 2 após a linha 8 do arquivo 1; ou, se alterar o arquivo 2 para o arquivo 1, exclua as linhas 12 a 15 do arquivo 2.

FcT Substitua as linhas no intervalo F do primeiro arquivo pelas linhas no intervalo T do segundo arquivo. É como uma adição e exclusão combinadas, mas mais compacta. Por exemplo, 5,7c8,10significa alterar as linhas 5-7 do arquivo 1 para ler como linhas 8-10 do arquivo 2; ou, se alterar o arquivo 2 para o arquivo 1, altere as linhas 8-10 do arquivo 2 para ler como linhas 5-7 do arquivo 1.

RdL Exclua as linhas no intervalo R do primeiro arquivo; a linha L é onde eles teriam aparecido no segundo arquivo se não tivessem sido excluídos. Por exemplo, 5,7d3significa excluir as linhas 5-7 do arquivo 1; ou, se alterar o arquivo 2 para o arquivo 1, acrescente as linhas 5-7 do arquivo 1 após a linha 3 do arquivo 2.

Veja também:


Então, para ver as laranjas, você teria que diferenciá-las lado a lado ou usando o contexto unificado.

No exemplo:

$ diff -y file1 file2
apples                                <
oranges                             oranges
                                  > apples

$ diff -u file1 file2
@@ -1,2 +1,2 @@
-apples
 oranges
+apples
kenorb
fonte