Wynik różnic dwóch plików z przełączanymi liniami mówi, że dwukrotnie brakuje tej samej linii


28

Próbuję zrozumieć polecenie linux diff na dwóch plikach, których linie są po prostu wzajemną permutacją, ale nie są w stanie odczytać generowanych danych wyjściowych. Rozważ trzy poniższe polecenia:

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

Czy ktoś może wyjaśnić powyższe tajemnicze wyjście z diff.

  1. Dlaczego w ogóle nie ma wzmianki o „pomarańczach” na wyjściu?
  2. Co znaczy 1d0i co 2a2oznacza?

Rozumiem z tej odpowiedzi, że:

„<” oznacza brak wiersza w pliku2, a „>” oznacza brak wiersza w pliku1

ALE to nie wyjaśnia, dlaczego brakuje pomarańczy na wyjściu.


12
Ponieważ orangesjest to największa wspólna część między dwoma plikami, więc otrzymujesz najkrótszy sposób na wyrażenie różnic między tymi dwoma plikami.
Stéphane Chazelas

10
A jeśli chcesz uzyskać bardziej czytelne wyjście, po prostu użyj diff -u file1 file2zamiast tego. Nazywa się to formatem „Unified Diff”. Oryginalny format różnic miał być bardzo kompaktowy, ale zunifikowane różnice mają być znacznie bardziej czytelne.
godlygeek

4
@godlygeek Ordiff -y file1 file2
user80551

Odpowiedzi:


27

Aby zrozumieć raport, pamiętaj, że diffma on charakter nakazowy i opisuje, jakie zmiany należy wprowadzić w pierwszym pliku ( file1), aby był taki sam jak w drugim pliku ( file2).

W szczególności din 1d0oznacza usunięcie, a ain 2a2oznacza dodanie .

A zatem:

  • 1d0oznacza, że ​​wiersz 1 należy usunąć w file1( apples). 0w 1d0drodze linia 0, gdzie będą pojawiały się w drugim pliku ( file2), gdyby nie został usunięty. Oznacza to, że przy zmianie file2na file1(wstecz) dołącz wiersz 1 file1po wierszu 0 z file2.
  • 2a2oznacza dołączenie drugiej linii ( oranges) file2do teraz drugiej linii file1(po usunięciu pierwszej linii file1, orangesprzełączony na linię 1)

co jest 0w 1d0środku
Geek

@Geek zobacz moją edycję
chaos

1
@Geek Ale bądź ostrożny, ponieważ mogą robić węzły w mózgu =)
chaos

to rzeczywiście zaczęło robić węzły :-)
Geek

13

Rozważ te pliki:

file1:

# cat file1
apples
pears
oranges
peaches

file2:

# cat file2
oranges
apples
peaches
ananas
banana

Jak to diffdziała, pod warunkiem, że jest oparte na zamówieniu:

  1. diffodczytuje pierwszy blok linii file1i file2, i próbuje znaleźć równe linie:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      -------------------------------
    ->oranges    ->oranges
      peaches      apples
                   peaches
                   ananas
                   banana
    
  2. Teraz pominie wszystkie wiersze, które są równe w obu plikach, co jest właśnie orangesw tym przypadku:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
      -------------------------------
    ->peaches    ->apples
                   peaches
                   ananas
                   banana
    
  3. Teraz znajdź kolejny zestaw podobnych linii i wydrukuj różnice:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      -------------------------------
    ->peaches    ->peaches
                   ananas
                   banana
    
  4. Pomiń podobne linie

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      peaches      peaches
      -------------------------------
    ->           ->ananas
                   banana
    
  5. Znajdź identyczne linie, jeśli to możliwe, i drukuj różnice:

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

Teraz, jeśli to zrobię diff file1 file2:

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

Teraz łatwo jest wyjaśnić, co diffoznacza wynik:

Aby file1wyrównać file2:

  • 1,2d0: Usuwanie ( d) linii 1-2z file1i modyfikacji linii 0z file2odpowiednio
  • 3a2: Dołącz ( a) linii 3w file1linii 2zfile2
  • 4a4,5: Dołącz do linii 4od file1linii 4-5zfile2

diffporównuje file1z file2linią po linii i wyrównuje różnice w pamięci tymczasowej. Po file1 wyrównywaniu do file2 pierwszego wystąpienia linii w file1, która również występuje w file2, wszystkie linie, które są równe aż do różnicy, nie są wymienione, często oznaczane jako ---. W tym przypadku istnieje tylko jedna podobna linia, którą jest oranges. Zauważ, że powiedziałem file1równy file2, więc file1jest postrzegany względem, file2a nie na odwrót.

W tym przypadku dane wyjściowe odnoszą się do pierwszego podanego pliku file1.


2
Nie podoba mi się wstępne wyjaśnienie: appleswystępuje również w obu plikach.
LUB Mapper

1
@ORMapper Zmieniłem wyjaśnienie. Czy teraz brzmi to lepiej / lepiej :)?
polym

Nie do końca, na razie napisałeś „istnieje tylko jedna podobna linia, która jest oranges”. Źle: Istnieją dwie linie, które są nie tylko podobne , ale absolutnie identyczne . Jeden z nich czyta oranges, drugi czyta apples. Również twoje wyjaśnienie (oparte wyłącznie na zamówieniu) jest sprzeczne z komentarzem Stéphane'a do pytania (opartym na długości) - kto ma rację?
LUB Mapper

@ORMapper Zapomniałeś „W tym przypadku” i wiersze przed tym. Miałem na myśli, że na tym etapie jest tylko jedna podobna linia. Dodam tylko przykład do mojej odpowiedzi, aby można ją było lepiej zrozumieć.
polim

1
@ORMapper Czy możesz mi podać przykład, który pokazuje, że odpowiedź na podstawie długości jest poprawna?
polim

8

Oto one:

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

8

Standardowy (stary) format wyjściowy wyświetla różnicę między plikami bez otaczającego tekstu z obszarami, w których pliki się różnią.

Na przykład: 1d0 <(usuń) oznacza, że jabłka muszą zostać usunięte z 1. wiersza file1, a 2a2 >(dołącz) oznacza, że jabłka należy dodać do file22. wiersza, aby oba pliki można było dopasować.

Dokumentacja dostępna na stronie info diffwyjaśnia to dalej:

Pokazywanie różnic bez kontekstu

„Normalny” diffformat wyjściowy pokazuje każdą porcję różnic bez otaczającego kontekstu. Czasami takie wyjście jest najczystszym sposobem, aby zobaczyć, jak zmieniły się linie, bez bałaganu w pobliżu niezmienionych linii (chociaż można uzyskać podobne wyniki z kontekstem lub ujednoliconymi formatami, używając 0 linii kontekstu). Jednak ten format nie jest już powszechnie używany do wysyłania łat; w tym celu format kontekstowy i format ujednolicony są lepsze. Normalny format jest domyślny dla zgodności ze starszymi wersjami diffi standardem POSIX. Użyj --normalopcji, aby jawnie wybrać ten format wyjściowy.

Szczegółowy opis formatu normalnego

Normalny format wyjściowy składa się z jednego lub więcej fragmentów różnic; każdy przystojniak pokazuje jeden obszar, w którym różnią się pliki. Kawałki normalnego formatu wyglądają tak:

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

Istnieją trzy rodzaje poleceń zmiany. Każdy składa się z numeru linii lub zakresu linii oddzielonych przecinkami w pierwszym pliku, pojedynczego znaku wskazującego rodzaj zmiany, którą należy wprowadzić, oraz numeru linii lub zakresu oddzielonego przecinkami linii w drugim pliku. Wszystkie numery linii są oryginalnymi numerami linii w każdym pliku. Rodzaje poleceń zmiany są następujące:

LaR Dodaj linie z zakresu R drugiego pliku po linii L pierwszego pliku. Na przykład 8a12,15oznacza dołączanie wierszy 12-15 pliku 2 po wierszu 8 pliku 1; lub, jeśli zmieniasz plik 2 na plik 1, usuń wiersze 12-15 pliku 2.

FcT Zamień wiersze z zakresu F pierwszego pliku na wiersze z zakresu T drugiego pliku. To jest jak połączone dodawanie i usuwanie, ale bardziej kompaktowe. Na przykład 5,7c8,10oznacza zmianę wierszy 5-7 pliku 1 na odczytanie jako wiersze 8-10 pliku 2; lub, jeśli zmieniasz plik 2 na plik 1, zmień wiersze 8-10 pliku 2, tak aby były czytane jako wiersze 5-7 pliku 1.

RdL Usuń linie z zakresu R z pierwszego pliku; linia L to miejsce, w którym pojawiłyby się w drugim pliku, gdyby nie zostały usunięte. Na przykład 5,7d3oznacza usunięcie wierszy 5-7 pliku 1; lub, w przypadku zmiany pliku 2 na plik 1, dodaj wiersze 5-7 pliku 1 po wierszu 3 pliku 2.

Zobacz też:


Aby zobaczyć pomarańcze, musisz różnicować je obok siebie lub za pomocą ujednoliconego kontekstu.

W przykładzie:

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

$ diff -u file1 file2
@@ -1,2 +1,2 @@
-apples
 oranges
+apples
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.