Kein Zeilenumbruch am Dateiende


472

Wenn Sie dies tun git diff, wird "Kein Zeilenumbruch am Ende der Datei" angezeigt .

Ok, am Ende der Datei befindet sich kein Zeilenumbruch. Was ist die große Sache?

Welche Bedeutung hat die Nachricht und was versucht sie uns zu sagen?


11
Wenn Sie eine Datei haben, die ohne Zeilenumbruch endet, und eine weitere Zeile hinzufügen, muss git möglicherweise anzeigen, dass sich die letzte Zeile geändert hat, da sie das Zeilenumbruchzeichen als Teil der Zeile enthält.
Nafg

Antworten:


458

Es zeigt an, dass Sie '\n'am Ende der Datei keinen Zeilenumbruch haben (normalerweise auch bekannt als CR oder CRLF).

Das heißt, einfach gesagt, das letzte Byte (oder Bytes, wenn Sie unter Windows arbeiten) in der Datei ist keine neue Zeile.

Die Meldung wird angezeigt, da es ansonsten keine Möglichkeit gibt, den Unterschied zwischen einer Datei, in der am Ende eine neue Zeile steht, und einer Datei, in der dies nicht der Fall ist, zu erkennen. Diff muss sowieso eine neue Zeile ausgeben, sonst ist das Ergebnis schwerer zu lesen oder automatisch zu verarbeiten.

Beachten Sie, dass es ein guter Stil ist, die Zeilenumbruch immer als letztes Zeichen einzufügen, wenn das Dateiformat dies zulässt. Darüber hinaus ist es beispielsweise für C- und C ++ - Headerdateien vom Sprachstandard erforderlich.


136
Können Sie aus Neugier erklären, warum es als guter Stil angesehen wird, immer eine neue Zeile als letzten Charakter zu verwenden? Bearbeiten: fand diese Diskussion .
Paul Bellora

84
@PaulBellora Historisch gesehen war es eine Entscheidung des C-Sprachstandards stackoverflow.com/a/729725/233098. Praktisch, weil viele Unix-Tools dies für eine ordnungsgemäße Anzeige erfordern oder erwarten . Stackoverflow.com/a/729795/233098 . Philosophisch gesehen sollte die letzte Zeile keine Ausnahme sein, da jede Zeile in einer Textdatei mit einem "Zeilenende" -Zeichen endet. Wenn wir anders darüber nachdenken, wollen wir das Gegenteil untersuchen. Wenn es anstelle von "Zeilenende" eine Markierung "Zeilenanfang" gäbe, würden Sie das Zeichen "Zeilenanfang" in der ersten Zeile weglassen?
Joe

29
@ Joe Das macht nicht so viel Sinn. Eine neue Zeile ist eine neue Zeile , dh das Trennzeichen zwischen den Zeilen, kein Zeilenende. Wir haben keine Zeilenanfangszeichen, da diese nicht erforderlich sind. Aus dem gleichen Grund haben wir keine Zeilenendezeichen.
Acjay

6
@acjay Ich behaupte, dass es von Natur aus besser zwischen "Trennzeichen zwischen Zeilen" und "Zeilenende" gibt. Keine der beiden Ansichten ist von Natur aus richtig oder falsch, nur eine Sichtweise. Ich schlage wir weiterhin den Point-of-View verwenden , die historisch praktisch ist, da wir bereits, dass es so zu tun und es macht Sinn , wenn Sie es akzeptieren. Konsistenz ist wichtig. Es ist nicht nötig, dies im Namen des Standpunkts "Trennzeichen zwischen Linien" zu brechen.
Joe

17
@WORMSS "Neu für mich" ist nicht dasselbe wie "eine neue Konvention". Dies ist wie das Entdecken einer anderen Art von Programmierkonvention. Du gehst einfach mit. Sie könnten abweichen, aber Sie isolieren sich nur. (Oder in diesem Fall tatsächlich Werkzeuge brechen.) Überlegen Sie, wie viele andere eine Rails-Konvention oder PEP8 entdeckt haben und wie konsistent diese Communities insgesamt geblieben sind, weil sie nachgegeben haben - obwohl sie im Gegenteil Code geschrieben haben.
Joe

100

Es ist nicht nur ein schlechter Stil, es kann zu unerwartetem Verhalten führen, wenn andere Tools in der Datei verwendet werden.

Hier ist test.txt:

first line
second line

In der letzten Zeile befindet sich kein Zeilenumbruchzeichen. Mal sehen, wie viele Zeilen in der Datei sind:

$ wc -l test.txt
1 test.txt

Vielleicht ist es das, was Sie wollen, aber in den meisten Fällen würden Sie wahrscheinlich erwarten, dass die Datei zwei Zeilen enthält.

Wenn Sie Dateien kombinieren möchten, verhält es sich möglicherweise nicht so, wie Sie es erwarten:

$ cat test.txt test.txt
first line
second linefirst line
second line

Schließlich würde es Ihre Unterschiede etwas lauter machen, wenn Sie eine neue Zeile hinzufügen würden. Wenn Sie eine dritte Zeile hinzufügen, wird sowohl die zweite Zeile als auch die neue Zeile bearbeitet.


4
Das Ergebnis von cat ist in Ordnung, aber der wc-Parameter "-l, --lines" ist einfach falsch. Sogar im Handbuch steht "Drucken der Zeilenumbrüche" und nicht "Zeilenzahlen drucken".
Der unglaubliche

Und ich kann dies nicht einmal (wc und cat) mit dem neuesten util linux (util-linux 2.34) reproduzieren.
Wget

1
@wget Ich bin unter util-linux 2.34 und es kann bestätigen, dass diese Antwort das aktuelle Verhalten beschreibt. Ich vermute, dass Ihr Editor das Zeichen "\ n" hinzugefügt hat.
stephanos

29

Der einzige Grund ist, dass Unix in der Vergangenheit eine Konvention für alle von Menschen lesbaren Textdateien hatte, die in einer neuen Zeile endeten. Zu diesem Zeitpunkt wurde eine zusätzliche Verarbeitung beim Anzeigen oder Verknüpfen von Textdateien vermieden und vermieden, dass Textdateien anders behandelt wurden als Dateien, die andere Arten von Daten enthalten (z. B. binäre Rohdaten, die nicht für Menschen lesbar sind).

Aufgrund dieser Konvention erwarten viele Tools aus dieser Zeit die abschließende Newline, einschließlich Texteditoren, unterschiedlichen Tools und anderen Textverarbeitungswerkzeugen. Mac OS X wurde auf BSD Unix aufgebaut, und Linux wurde so entwickelt, dass es Unix-kompatibel ist. Daher haben beide Betriebssysteme die gleiche Konvention, das gleiche Verhalten und die gleichen Tools geerbt.

Windows wurde nicht als Unix-kompatibel entwickelt, daher hat es nicht die gleiche Konvention, und die meisten Windows-Programme funktionieren ohne nachfolgende Zeilenumbrüche einwandfrei.

Da Git jedoch zuerst für Linux entwickelt wurde und viele Open-Source-Programme auf Unix-kompatiblen Systemen wie Linux, Mac OS X, FreeBSD usw. basieren, werden die meisten Open-Source-Communities und ihre Tools (einschließlich Programmiersprachen) fortgesetzt diese Konventionen zu befolgen.

Es gibt technische Gründe, die 1971 Sinn machten, aber in dieser Zeit ist es meistens Konvention und Aufrechterhaltung der Kompatibilität mit vorhandenen Werkzeugen.


23

Wenn Sie am Ende der vorhandenen Datei eine neue Textzeile hinzufügen, die am Ende noch keine enthält newline character, zeigt der Diff die alte letzte Zeile als geändert an, obwohl dies konzeptionell nicht der Fall war.

Dies ist mindestens ein guter Grund, newline characteram Ende ein hinzuzufügen .

Beispiel

Eine Datei enthält:

A() {
    // do something
}

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d              something.}

Sie bearbeiten es jetzt zu

A() {
    // do something
}
// Useful comment

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055  something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a    seful comment..

Das Git Diff zeigt:

-}
\ No newline at end of file
+}
+// Useful comment.

Mit anderen Worten, es zeigt einen größeren Unterschied als konzeptionell aufgetreten. Es zeigt, dass Sie die Zeile gelöscht }und hinzugefügt haben }\n. Dies ist in der Tat das, was passiert ist, aber es ist nicht das, was konzeptionell passiert ist, also kann es verwirrend sein.


2
Wir können dasselbe in die andere Richtung schreiben: Wenn Sie eine neue Zeile am Ende der vorhandenen Datei entfernen, die bereits eine neue Zeile am Ende hat, zeigt der Diff die alte letzte Zeile auch als geändert an, wenn dies konzeptionell nicht der Fall ist. Mindestens ein guter Grund, am Ende eine neue Zeile zu entfernen.
Gentiane

3
@gentiane Sie verwechseln "eine neue Zeile" (eine neue Zeile) und "eine neue Zeile" (1 oder 2 Zeichen, die das Ende einer Zeile begrenzen)
minexew

@minexew Nein, Gentiane nicht. Vielleicht merkt man einfach nicht, dass "eine neue Zeile" dasselbe ist wie "eine neue Zeile".
Der unglaubliche

3
@TheincredibleJan Wie sie in der Antwort verwendet werden, haben die beiden Begriffe unterschiedliche Bedeutungen. Ich weiß nicht, ob Sie versuchen, ein kluger Arsch zu sein, oder nur falsch verstehen, was los ist.
Minexew

18

Es zeigt nur an, dass das Ende der Datei keinen Zeilenumbruch enthält. Es ist keine Katastrophe, es ist nur eine Nachricht, um klarer zu machen, dass es keine gibt, wenn man sich einen Unterschied in der Befehlszeile ansieht.


10

Der Grund, warum diese Konvention in die Praxis umgesetzt wurde, liegt darin, dass unter UNIX-ähnlichen Betriebssystemen ein Zeilenumbruchzeichen als Zeilenabschluss und / oder Nachrichtengrenze behandelt wird (dies umfasst das Weiterleiten zwischen Prozessen, Zeilenpufferung usw.).

Stellen Sie sich zum Beispiel vor, dass eine Datei mit nur einem Zeilenumbruchzeichen als einzelne leere Zeile behandelt wird. Umgekehrt ist eine Datei mit einer Länge von null Bytes tatsächlich eine leere Datei mit null Zeilen. Dies kann gemäß dem wc -lBefehl bestätigt werden .

Insgesamt ist dieses Verhalten sinnvoll, da es keine andere Möglichkeit gibt, zwischen einer leeren Textdatei und einer Textdatei mit einer einzelnen leeren Zeile zu unterscheiden, wenn das \nZeichen lediglich ein Zeilentrennzeichen und kein Zeilenendezeichen wäre. Gültige Textdateien sollten daher immer mit einem Zeilenumbruchzeichen enden. Die einzige Ausnahme ist, wenn die Textdatei leer sein soll (keine Zeilen).


1
Warum bin ich -2 herabgestimmt? Ich habe nicht nur darauf hingewiesen, was andere Antworten angegeben haben (dh Standard-UNIX-basierte Tools erwarten eine neue Zeile als Terminator für Zeilen), sondern auch, dass es keine Möglichkeit gibt, eine leere Datei von einer einzelnen leeren Zeile zu unterscheiden, was absolut richtig ist . Ich beantwortete speziell die ursprüngliche Frage "Welche Bedeutung hat die Nachricht und was versucht sie uns zu sagen?"
Leslie Krause

Ich habe Sie nicht abgelehnt, aber diese Antwort scheint insofern spezifisch für Unix-Systeme zu sein, als sie nur gilt, wenn eine Newline nur das Newline-Zeichen ist. Es ist nicht klar, dass dies hier gilt. Die Warnung scheint auch nutzlos zu sein, wenn die Datei nur aus einer leeren Zeile besteht. Ich vermeide jedoch Stackoverflow, weil die Leute oft ohne Erklärung abstimmen.
user34660

9

Es gibt eine Sache, die ich in früheren Antworten nicht sehe. Die Warnung, dass kein Zeilenende vorhanden ist, kann eine Warnung sein, wenn ein Teil einer Datei abgeschnitten wurde. Dies könnte ein Symptom für fehlende Daten sein.


Guter Punkt im Allgemeinen, aber ich denke nicht, dass es im Kontext dieser speziellen Frage Sinn macht.
cst1992

@ cst1992 Antworten in Stackoverflow sollen so nützlich wie möglich sein, dh sie sollen auf alle Möglichkeiten zutreffen. Die Frage ist kurz und ich sehe nicht, wo sie die von mir vorgeschlagene Möglichkeit ausschließt.
user34660

7

Das Kernproblem besteht darin, was Sie als Zeile definieren und ob die Zeichenfolge am Ende der Zeile Teil der Zeile ist oder nicht. UNIX-basierte Editoren (wie VIM) oder Tools (wie Git) verwenden die EOL-Zeichenfolge als Zeilenabschluss, daher ist sie Teil der Zeile. Es ähnelt der Verwendung von Semikolon (;) in C und Pascal. In C beendet das Semikolon Anweisungen, in Pascal werden sie getrennt.


4

Dies verursacht tatsächlich ein Problem, da Zeilenenden automatisch geändert werden, um Dateien zu verschmutzen, ohne Änderungen daran vorzunehmen. Siehe diesen Beitrag zur Lösung.

Git ersetzt LF durch CRLF


3

Quelldateien werden häufig von Tools verkettet (C, C ++: Header-Dateien, Javascript: Bundler). Wenn Sie das Zeilenumbruchzeichen weglassen, können böse Fehler auftreten (wobei die letzte Zeile einer Quelle mit der ersten Zeile der nächsten Quelldatei verknüpft ist). Hoffentlich fügen alle Quellcode-Concat-Tools eine neue Zeile zwischen verketteten Dateien ein, aber das scheint nicht immer der Fall zu sein.

Der Kern des Problems ist: In den meisten Sprachen haben Zeilenumbrüche eine semantische Bedeutung, und das Dateiende ist keine sprachdefinierte Alternative für das Zeilenumbruchzeichen. Sie sollten also jede Anweisung / jeden Ausdruck mit einem Zeilenumbruchzeichen beenden - einschließlich des letzten.


1
In C / C ++ können Sie Ihr gesamtes Projekt in einer Zeile schreiben. Keine Notwendigkeit für Newline.
Der unglaubliche

Sie könnten Ihr gesamtes Projekt in einer Zeile schreiben ... wenn Sie keinen //Stilkommentar in der Mitte des Codes verwenden.
Doug Coburn

2

Ihre Originaldatei hatte wahrscheinlich kein Zeilenumbruchzeichen.

Einige Editoren wie gedit unter Linux fügen jedoch stillschweigend Zeilenumbrüche am Ende der Datei hinzu. Sie können diese Meldung nicht entfernen, wenn Sie diese Art von Editoren verwenden.

Ich habe versucht, dieses Problem zu beheben, indem ich die Datei mit dem Visual Studio Code Editor geöffnet habe

Dieser Editor zeigt deutlich die letzte Zeile an und Sie können die Zeile nach Belieben löschen.


0

Ich bin darauf gestoßen, als ich ein IntelliJ-Projekt auf einem Mac erstellt und das Projekt dann auf meinen Windows-Computer verschoben habe. Ich musste jede Datei manuell öffnen und die Codierungseinstellung unten rechts im IntelliJ-Fenster ändern. Wahrscheinlich nicht den meisten, die diese Frage gelesen haben, aber das hätte mir ein paar Stunden Arbeit ersparen können ...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.