Różnica w białych znakach między dwoma plikami w systemie Linux

15

Mam dwa pliki, które porównując z diff pokazują, że każda linia się zmieniła. Kiedy porównuję je z diff -w(ignorując białe znaki), pokazuje kilka minimalnych zmian, których oczekuję.

Oczywiście istnieje pewna różnica między białymi spacjami w każdym pliku, ale nie wiem, czym one są ani jak je znaleźć. Próbowałem edytować pliki, aby upewnić się, że białe znaki są w rzeczywistości znakami spacji (w przeciwieństwie do tabulatorów), ale nie jestem pewien, co jeszcze można zrobić.

Użyłem vim z, :set list onaby potwierdzić, że na końcu linii nie ma spacji końcowych.

Uważam również, że każdy plik ma terminatory linii Linuxa, ponieważ vim nie pokazywał ^Mkońca linii.

Romski
źródło
1
Czy sprawdziłeś końcowe spacje (na końcu linii)? Takie miejsce zostanie wykryte przez, diffale wielu redaktorów i tak domyślnie nie czyni tego miejsca widocznym.
John1024
Dobry pomysł. Użyłem vima z „: set list na”, to pokazało „$” na końcu linii i nie było spacji końcowych. Zaktualizuję moje pytanie
Romski
Jeśli jesteś vimużytkownikiem, to czy próbowałeś vimdiff file1 file2zobaczyć, jakie są różnice?
John1024
@ John1024 Nie byłem świadomy vimdiff, ale wygląda obiecująco. Dodaj to jako odpowiedź, a zaakceptuję
Romski
1
Vim pokazuje ^ M tylko wtedy, gdy źle wykrywa zakończenie linii uniksowej, ale plik faktycznie ma zakończenie linii DOS. Zwykle dzieje się tak, jeśli masz mieszane zakończenie linii w jednym pliku, np. Zastosowanie poprawki z innym zakończeniem linii niż plik oryginalny. Kiedy vim wykryje poprawne zakończenie linii DOS, nie pokazałby ^ M.
Lie Ryan

Odpowiedzi:

7

Dla vimużytkowników jest przydatne narzędzie, które pokazuje dokładne różnice między plikami:

vimdiff file1 file2

Spowoduje to umieszczenie każdego pliku w oknach, obok siebie i różnic z podświetlonym kolorem.

Kilka przydatnych poleceń, gdy w vimdiff

Podczas gdy vimdiffniektóre przydatne polecenia to:

  • ]c: przejdź do następnej zmiany

  • [c: przejdź do poprzedniej zmiany

  • ctrl-W ctrl-W: przejdź do innego okna

  • zo: otwarte fałdy

  • zc: zamknij fałdy

Przykład

Oto przykład vimdiffW xtermporównujących dwie wersje cupspliku konfiguracyjnego:

wprowadź opis zdjęcia tutaj

Widać, że długie odcinki identycznych linii zostały zwinięte. Można je ponownie otworzyć za pomocą zo.

Schemat kolorów będzie się różnić w zależności od ustawień opcji. W powyższym przykładzie, gdy linia pojawia się w jednym pliku, ale nie w drugim, linia ma ciemnoniebieskie tło. W drugim pliku brakujące linie są oznaczone liniami przerywanymi. Kiedy linia pojawia się w obu plikach, ale ma pewne różnice, niezmienione części linii mają różowe tło, a zmienione części mają czerwone tło.

John1024
źródło
14

W FreeBSD lub w większości systemów Linux można przesyłać dane wyjściowe z pliku diff, cat -v -e -taby pokazać różnice między białymi spacjami.

diff file1 file2 | cat -vet

Karty będą wyświetlane jako ^I, a $na końcu każdej linii, aby można było zobaczyć końcowe białe znaki, a znaki niedrukowalne będą wyświetlane jako ^Xlub M-X.

Jeśli masz jądra GNU (dostępne w większości dystrybucji Linuksa, które nie są zajęte), można to uprościć

diff file1 file2 | cat -A

W systemach busybox użyj catv -vet.

Mark Plotnick
źródło
2

Czy jeden z plików był edytowany na komputerze z systemem Windows?

Standardowym zakończeniem linii w systemie Windows jest CRLF, gdzie w Linuksie jest to po prostu LF (a na komputerach Mac był to CR, ale podejrzewam, że zmieniło się to od OS X).

Wypróbuj wc -lpliki i sprawdź, ile wierszy, a następnie sprawdź, czy różnica wielkości jest taka sama jak liczba wierszy (ostatni wiersz może nie zostać zakończony w jednym pliku).

płot
źródło
Dziękuję za szybką odpowiedź. Wykonanie liczby wierszy pokazuje, że jeden plik ma jeszcze 5 wierszy (oczekuję tego po dokonaniu edycji). Mam jeden plik z komputera z systemem Linux, a drugi został pobrany z repozytorium kodu do systemu Linux. Wierzę, że przeglądanie pliku z terminatorami Windows w vimie pokaże ostatni znak jako ^ M i tak nie jest.
Romski
3
vim jest w rzeczywistości wystarczająco inteligentny, aby automatycznie wykryć zakończenie linii, zobacz stackoverflow.com/questions/3852868 w celu uzyskania szczegółowych informacji.
płot
Nie byłam tego świadoma! Sprawdzę ponownie
Romski
2

odmoże pomóc. Polecenie Octal Dump może wyświetlać zawartość w systemie szesnastkowym. Pomoże to zobaczyć, jakie bajty, w tym bajty zerowe lub nieoczekiwane białe znaki, znajdują się w pliku. Możliwe typowe przyczyny to LF vs CRLF, tabulatory vs spacje lub ASCII vs Unicode (które często mogą mieć po prostu bajt zerowy przed każdym normalnie widocznym bajtem). od -x filenamepowinien ujawnić dowolny z tych wzorów. Jeśli chcesz bardziej skomplikowanego sposobu przeglądania pliku, każdy „edytor szesnastkowy” może zrobić to dobrze. Zaletą odjest to, że podobnie jak cutpolecenie, jest wbudowany w wiele systemów uniksowych. Dlatego często nie jest wymagana osobna instalacja.

Jeśli potrzebujesz bardziej podobnych plików, trmożesz wprowadzić zmiany i sedwięcej. Najprawdopodobniej zacznę od ls -lsprawdzenia, który plik jest większy, a następnie od wyświetlenia bajtów, aby zobaczyć, co należy zmienić, a następnie zmień jeden z plików, aby wyglądały bardziej podobnie.

TOOGAM
źródło
1

Aby dowiedzieć się, gdzie są prawdziwe białe znaki i tabulatory, możesz je zastąpić, sedna przykład:

$ cat file
  line 1
  line 2
    line 6
        line 7
$ sed 's/ /-/g; s/\t/<tab>/g' file
--line-1
--line-2
<tab>line-6
<tab><tab>line-7

A teraz porównaj dwa pliki.

chaos
źródło
Co więcej, możesz uruchomić ten filtr na wyjściu diff. Lub możesz użyć gotowego filtra cat, jak w superuser.com/a/913368/37154
clacke
0

Poniższa treść została skopiowana tutaj z sekcji „pytanie” powyżej, napisanej przez Romskiego.

Zarówno vimdiffi diff file1 file2 | cat -Abyły bardzo przydatne z punktu widzenia narzędzi.

Wreszcie znalazłem jeszcze jeden problem. Niektóre z moich plików zostały zakodowane przy pomocy UTF-8 BOM. Zostało to podkreślone za pomocą diff file1 file2 | cat -A. Przejawiało się to M-oM-;M-?na początku pliku, którego dotyczy problem:

$ diff file1 file2 | cat -A
< package com.mycompany;$
---$
> M-oM-;M-?package com.mycompany;$

Chociaż było wiele problemów, wymieniłem poniżej kilka poleceń dla tych, którzy muszą wyczyścić swoje pliki:

# recursively remove UTF8 BOM
find . -type f -exec sed -i -e '1s/^\xEF\xBB\xBF//' {} \;

# recursively replace CRLF with LF
find . -type f -print0 | xargs -0 dos2unix
Kevin Panko
źródło