Resultado do diff dois arquivos 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 permutáveis entre si, mas não são capazes de aumentar 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 oculta acima do diff.

  1. Por que não há menção de "laranjas" na saída?
  2. O que significa 1d0 e 2a2 ?

Eu entendo desta resposta que:

"<" means the line is missing in file2 and ">" means the line is missing in file1

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

    
por Geek 25.07.2014 / 12:22

4 respostas

26

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, o d em 1d0 significa excluir e o a em 2a2 significa adicionar .

Assim:

  • 1d0 significa que a linha 1 deve ser excluída em file1 ( apples ). 0 in 1d0 significa que a linha 0 é onde eles apareceriam no segundo arquivo ( file2 ) caso não tivessem sido excluídos. Isso significa que, ao alterar file2 para file1 (para trás), anexe a linha 1 de file1 após a linha 0 de file2 .
  • 2a2 significa anexar a segunda linha ( oranges ) de file2 à agora segunda linha de file1 (depois de excluir a primeira linha em file1 , oranges alternou para a linha 1)
por 25.07.2014 / 12:34
12

Considere estes arquivos:

file1 :

# cat file1
apples
pears
oranges
peaches

file2 :

# cat file2
oranges
apples
peaches
ananas
banana

Como o diff funciona, já que é baseado em ordem:

  1. diff lê o primeiro bloco de linhas de file1 e 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 ignorará todas as linhas que são iguais nos dois arquivos, o que é apenas oranges neste 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 as 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 as 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 a saída de diff significa:

Para tornar file1 igual a file2 :

  • 1,2d0 : Excluir ( d ) linhas 1-2 de file1 e modificar a linha 0 de file2 de acordo
  • 3a2 : Anexar ( a ) à linha 3 de file1 linha 2 de file2
  • 4a4,5 : Anexar à linha 4 de file1 lines 4-5 de file2

diff compara file1 com file2 linha por linha e resolve as diferenças na memória temporária. Depois de tornar file1 igual a file2 até a primeira ocorrência de uma linha em file1 , que também ocorre em file2 , todas as linhas iguais até uma diferença não são mencionadas, frequentemente indicado como --- . Nesse caso, há apenas uma linha semelhante, que é oranges . Note que eu disse file1 igual a file2 , então file1 é visto em relação a file2 e não o contrário.

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

    
por 25.07.2014 / 12:37
8

Lá estão eles:

$ diff file1 file2
1d0
< apples
2a2
> apples
$ diff file2 file1
1d0
< oranges
2a2
> oranges
    
por 25.07.2014 / 13:06
8

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

Por exemplo: 1d0 < (delete) significa que as maçãs precisam ser removidas da 1a linha de file1 e 2a2 > (anexar) significa as maçãs precisa ser adicionado em file2 na segunda linha, para que ambos os arquivos possam ser correspondidos.

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

Showing Differences Without Context

The "normal" diff output format shows each hunk of differences without any surrounding context. Sometimes such output is the clearest way to see how lines have changed, without the clutter of nearby unchanged lines (although you can get similar results with the context or unified formats by using 0 lines of context). However, this format is no longer widely used for sending out patches; for that purpose, the context format and the unified format are superior. Normal format is the default for compatibility with older versions of diff and the POSIX standard. Use the --normal option to select this output format explicitly.

Detailed Description of Normal Format

The normal output format consists of one or more hunks of differences; each hunk shows one area where the files differ. Normal format hunks look like this:

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

There are three types of change commands. Each consists of a line number or comma-separated range of lines in the first file, a single character indicating the kind of change to make, and a line number or comma-separated range of lines in the second file. All line numbers are the original line numbers in each file. The types of change commands are:

LaR Add the lines in range R of the second file after line L of the first file. For example, 8a12,15 means append lines 12-15 of file 2 after line 8 of file 1; or, if changing file 2 into file 1, delete lines 12-15 of file 2.

FcT Replace the lines in range F of the first file with lines in range T of the second file. This is like a combined add and delete, but more compact. For example, 5,7c8,10 means change lines 5-7 of file 1 to read as lines 8-10 of file 2; or, if changing file 2 into file 1, change lines 8-10 of file 2 to read as lines 5-7 of file 1.

RdL Delete the lines in range R from the first file; line L is where they would have appeared in the second file had they not been deleted. For example, 5,7d3 means delete lines 5-7 of file 1; or, if changing file 2 into file 1, append lines 5-7 of file 1 after line 3 of file 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
    
por 25.07.2014 / 14:57

Tags