Unterschied im Whitespace zwischen zwei Dateien unter Linux

8147
Romski

Ich habe zwei Dateien, die beim Vergleich mit diff zeigen, dass sich jede Zeile geändert hat. Wenn ich sie mit diff -w(ohne Whitespace) vergleiche, werden die wenigen minimalen Änderungen angezeigt, die ich erwarte.

Natürlich gibt es einige Unterschiede zwischen den Leerzeichen in jeder Datei, aber ich weiß nicht, was sie sind oder wie ich sie finden kann. Ich habe versucht, die Dateien zu bearbeiten, um sicherzustellen, dass der Leerraum tatsächlich Leerzeichen ist (im Gegensatz zu Tabulatoren). Ich bin jedoch nicht sicher, was er sonst tun soll.

Ich habe vim mit verwendet :set list on, um zu bestätigen, dass am Ende der Zeilen kein Leerzeichen vorhanden ist.

Ich glaube auch, dass jede Datei über Linux-Terminatoren verfügt, da vim das ^Mam Ende der Zeilen nicht angezeigt hat .

14
Haben Sie nach dem Leerzeichen gesucht (am Ende einer Zeile)? Ein solcher Speicherplatz wird von 'diff' erkannt, aber viele Editoren machen diesen Platz standardmäßig nicht sichtbar. John1024 vor 9 Jahren 1
Guter Vorschlag. Ich habe vim mit ": set list on" verwendet, hier wurde das "$" am Ende der Zeile angezeigt und es gab kein Leerzeichen. Ich werde meine Frage aktualisieren Romski vor 9 Jahren 0
Wenn Sie ein Benutzer von `vim` sind, haben Sie versucht, mithilfe von` vimdiff file1 file2` die Unterschiede zu erkennen? John1024 vor 9 Jahren 0
@ John1024 Ich wusste nichts von Vimdiff, aber es sieht vielversprechend aus. Fügen Sie es als Antwort hinzu und ich akzeptiere Romski vor 9 Jahren 0
Vim zeigt ^ M nur dann, wenn ein Unix-Zeilenende falsch erkannt wird, die Datei jedoch ein DOS-Zeilenende hat. Normalerweise geschieht dies, wenn Sie gemischte Zeilen haben, die in einer einzelnen Datei enden, z. B. einen Patch mit anderen Zeilenenden als die Originaldatei. Wenn vim erkennt, dass die DOS-Zeile korrekt endet, hätte es nicht das ^ M angezeigt. Lie Ryan vor 9 Jahren 1

6 Antworten auf die Frage

12
Mark Plotnick

Auf FreeBSD oder den meisten Linux-Systemen können Sie die Ausgabe von diff cat -v -e -tdurchleiten, um Unterschiede zwischen den Whitespaces anzuzeigen.

diff file1 file2 | cat -vet 

Registerkarten werden als angezeigt ^I, $am Ende jeder Zeile wird ein angezeigt, so dass Sie Leerzeichen nachfolgen können und nicht druckbare Zeichen als ^Xoder angezeigt werden M-X.

Wenn Sie über GNU-Coreutils verfügen (verfügbar bei den meisten Linux-Distributionen, die nicht mit dem Bus beschäftigt sind), kann dies vereinfacht werden

diff file1 file2 | cat -A 

Verwenden Sie auf ausgelasteten Systemen catv -vet.

6
John1024

Für vimBenutzer gibt es ein praktisches Hilfsprogramm, um genaue Unterschiede zwischen Dateien anzuzeigen:

vimdiff file1 file2 

Dadurch wird jede Datei nebeneinander in Fenstern angezeigt, und die farblich hervorgehobenen Unterschiede werden angezeigt.

Einige nützliche Befehle in vimdiff

Während in vimdiff, sind einige nützliche Befehle:

  • ]c: zur nächsten Änderung springen

  • [c: zur vorherigen Änderung springen

  • ctrl-W ctrl-W: Wechseln Sie in ein anderes Fenster

  • zo: Falten öffnen

  • zc: Falten schließen

Beispiel

Hier ist ein Beispiel für vimdiffin einem xtermVergleich von zwei Versionen einer cupsKonfigurationsdatei:

enter image description here

Sie können sehen, dass lange Abschnitte identischer Linien reduziert wurden. Sie können mit wieder geöffnet werden zo.

Das Farbschema hängt von Ihren Optionseinstellungen ab. Wenn im obigen Beispiel eine Zeile in einer Datei angezeigt wird, nicht jedoch in der anderen, wird diese Zeile dunkelblau hinterlegt. In der anderen Datei werden die fehlenden Zeilen durch gestrichelte Linien angezeigt. Wenn eine Linie in beiden Dateien angezeigt wird, es jedoch Unterschiede gibt, sind die unveränderten Teile der Linien rosa unterlegt und die geänderten Teile sind rot hinterlegt.

2
fencepost

Wurde eine der Dateien auf einem Windows-Computer bearbeitet?

Die Standard-Leitungsbeendigung unter Windows ist CRLF. Unter Linux ist dies einfach LF (und auf Macs war es früher CR, aber ich vermute, dass sich das seit OS X geändert hat).

Probieren Sie wc -ldie Dateien aus und prüfen Sie, wie viele Zeilen vorhanden sind. Prüfen Sie dann, ob der Größenunterschied der Anzahl der Zeilen entspricht (letzte Zeile wird möglicherweise nicht in einer Datei abgeschlossen).

Danke für die schnelle Antwort. Eine Zeilenzählung zeigt, dass eine Datei 5 weitere Zeilen hat (ich erwarte dies, da ich Änderungen vorgenommen habe). Ich habe eine Datei von einer Linux-Maschine erhalten und die andere wurde von einem Code-Repository auf Linux ausgecheckt. Ich glaube, dass das Anzeigen einer Datei mit Windows-Terminatoren in vim das letzte Zeichen als ^ M anzeigt, und das ist nicht der Fall. Romski vor 9 Jahren 0
vim ist tatsächlich intelligent genug, um die Leitungsbeendigung automatisch zu erkennen. Weitere Informationen finden Sie unter https://stackoverflow.com/questions/3852868. fencepost vor 9 Jahren 3
Das wusste ich nicht! Ich werde es nochmal überprüfen Romski vor 9 Jahren 0
2
TOOGAM

odkann helfen Der Octal Dump-Befehl kann den Inhalt hexadezimal anzeigen. Auf diese Weise können Sie feststellen, welche Bytes (einschließlich null Bytes oder unerwarteter Leerraum) in einer Datei enthalten sind. Mögliche häufige Ursachen können LF vs CRLF, Tabs vs Leerzeichen oder ASCII vs Unicode sein (die oft nur ein Null-Byte vor jedem normalerweise sichtbaren Byte haben). od -x filenamesollte eines dieser Muster offenbaren. Wenn Sie eine ausführlichere Ansicht der Datei wünschen, kann jeder "Hex-Editor" gut geeignet sein. Das Schöne daran odist, dass es wie der cutBefehl in viele Unix-Systeme integriert ist. Daher ist häufig keine separate Installation erforderlich.

Wenn Sie Dateien ähnlicher benötigen, trkönnen Sie einige Änderungen vornehmen und sedmehr machen. Ich würde wahrscheinlich damit anfangen ls -lzu sehen, welche Datei größer ist, dann Bytes anzeigen, um zu sehen, was geändert werden muss, und dann eine der Dateien so ändern, dass sie ähnlicher erscheinen.

1
chaos

Um herauszufinden, wo sich echte Leerzeichen und Tabulatoren befinden, können Sie sie ersetzen, indem Sie sedbeispielsweise Folgendes verwenden :

$ 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 

Und jetzt vergleichen Sie die beiden Dateien.

Noch besser, Sie können diesen Filter für die diff-Ausgabe ausführen. Oder Sie können den vorgefertigten Filter in `cat` verwenden, wie in http://superuser.com/a/913368/37154 clacke vor 9 Jahren 0
0
Kevin Panko

Der folgende Inhalt wurde hier aus dem obigen Abschnitt "Frage" kopiert, der von Romski geschrieben wurde.

Beides vimdiffund diff file1 file2 | cat -Awaren aus Werkzeugsicht sehr nützlich.

Zum Schluss habe ich noch ein weiteres Problem gefunden. Einige meiner Dateien wurden mit UTF-8 BOM codiert. Dies wurde mit hervorgehoben diff file1 file2 | cat -A. Dies manifestierte sich wie M-oM-;M-?am Anfang der betroffenen Datei:

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

Während es einige Probleme gab, habe ich nachfolgend einige Befehle für diejenigen aufgelistet, die ihre Dateien bereinigen müssen:

# 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