Ich nehme an, dass jeder hier mit dem Sprichwort vertraut ist, dass alle Textdateien mit einem Zeilenumbruch enden sollten. Ich kenne diese "Regel" schon seit Jahren, aber ich habe mich immer gefragt, warum?
Antworten
Zu viele Anzeigen?Denn das ist wie der POSIX-Standard eine Zeile :
3.206 Zeile
Eine Folge von null oder mehr Nicht-<Newline>-Zeichen plus einem abschließenden <Newline>-Zeichen.
Daher gelten Zeilen, die nicht mit einem Zeilenumbruch enden, nicht als echte Zeilen. Deshalb haben manche Programme Probleme, die letzte Zeile einer Datei zu verarbeiten, wenn sie nicht mit einem Zeilenumbruch abgeschlossen ist.
Bei der Arbeit mit einem Terminalemulator hat diese Richtlinie zumindest einen entscheidenden Vorteil: Alle Unix-Tools erwarten diese Konvention und arbeiten mit ihr. Wenn Sie zum Beispiel Dateien verketten mit cat
Eine Datei, die mit einem Zeilenumbruch abgeschlossen wird, hat eine andere Wirkung als eine Datei ohne Zeilenumbruch:
$ more a.txt
foo
$ more b.txt
bar$ more c.txt
baz
$ cat {a,b,c}.txt
foo
barbaz
Und wie das vorherige Beispiel zeigt, kann die Datei auch auf der Kommandozeile angezeigt werden (z. B. über more
), führt eine Datei mit Zeilenumbruch zu einer korrekten Anzeige. Eine nicht ordnungsgemäß beendete Datei kann verstümmelt werden (zweite Zeile).
Aus Gründen der Konsistenz ist es sehr hilfreich, diese Regel zu befolgen - andernfalls entsteht zusätzlicher Aufwand beim Umgang mit den Standard-Unix-Werkzeugen.
Denken Sie einmal anders darüber nach: Wenn Zeilen nicht durch einen Zeilenumbruch beendet werden, werden Befehle wie cat
nützlich ist, ist viel schwieriger: Wie kann man einen Befehl zur Verkettung von Dateien so gestalten, dass
- wird der Anfang jeder Datei in eine neue Zeile gesetzt, was in 95 % der Fälle erwünscht ist; aber
- ermöglicht es, die letzte und erste Zeile zweier Dateien zusammenzuführen, wie im obigen Beispiel zwischen
b.txt
yc.txt
?
Natürlich ist dies auflösbar aber Sie müssen die Verwendung von cat
komplexer (durch Hinzufügen von Positionsargumenten in der Befehlszeile, z. B. cat a.txt --no-newline b.txt c.txt
), und jetzt die Befehl und nicht jede einzelne Datei steuert, wie sie mit anderen Dateien zusammengefügt wird. Dies ist mit Sicherheit nicht sehr praktisch.
Oder Sie müssen ein spezielles Sentinel-Zeichen einführen, um eine Zeile zu markieren, die nicht beendet, sondern fortgesetzt werden soll. Nun, jetzt haben Sie die gleiche Situation wie bei POSIX, nur in umgekehrter Form (Zeilenfortsetzung statt Zeilenendzeichen).
Jetzt, am <em>nicht POSIX-konform </em>Systemen (heutzutage ist das meist Windows) ist der Punkt strittig: Dateien enden in der Regel nicht mit einem Zeilenumbruch, und die (informelle) Definition einer Zeile könnte zum Beispiel "Text, der <em>getrennt </em>durch Zeilenumbrüche" (man beachte die Betonung). Das ist völlig richtig. Bei strukturierten Daten (z. B. Programmiercode) macht es das Parsen jedoch minimal komplizierter: Es bedeutet im Allgemeinen, dass Parser neu geschrieben werden müssen. Wenn ein Parser ursprünglich mit Blick auf die POSIX-Definition geschrieben wurde, kann es einfacher sein, den Token-Stream zu ändern als den Parser - mit anderen Worten, ein "künstliches Newline"-Token am Ende der Eingabe hinzuzufügen.
Jede Zeile sollte mit einem Zeilenumbruch abgeschlossen werden, auch die letzte. Einige Programme haben Probleme bei der Verarbeitung der letzten Zeile einer Datei, wenn diese nicht mit einem Zeilenumbruch abgeschlossen ist.
Der GCC warnt davor, nicht weil er kann nicht die Datei verarbeiten, sondern weil sie muss als Teil der Norm.
Der Standard der Sprache C besagt Eine Quelldatei, die nicht leer ist, muss mit einem Zeilenumbruch enden, dem nicht unmittelbar ein Backslash-Zeichen vorausgehen darf.
Da es sich um eine "Soll"-Klausel handelt, muss bei einem Verstoß gegen diese Regel eine Diagnosemeldung ausgegeben werden.
Dies steht in Abschnitt 2.1.1.2 des ANSI C 1989-Standards. Abschnitt 5.1.1.2 der ISO C 1999-Norm (und wahrscheinlich auch der ISO C 1990-Norm).
Referenz: Das GCC/GNU-Mailarchiv .
Diese Antwort ist eher der Versuch einer technischen Antwort als eine Meinung.
Wenn wir POSIX-Puristen sein wollen, definieren wir eine Zeile als:
Eine Folge von null oder mehr Nicht-<Newline>-Zeichen plus einem abschließenden <Newline>-Zeichen.
Quelle: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206
Eine unvollständige Zeile als:
Eine Folge von einem oder mehreren Nicht-<Newline>-Zeichen am Ende der Datei.
Quelle: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195
Eine Textdatei als:
Eine Datei, die Zeichen enthält, die in null oder mehr Zeilen organisiert sind. Die Zeilen enthalten keine NUL-Zeichen und keine darf länger als {LINE_MAX} Bytes sein, einschließlich des <Newline>-Zeichens. Obwohl POSIX.1-2008 nicht zwischen Textdateien und Binärdateien unterscheidet (siehe ISO C-Standard), erzeugen viele Dienstprogramme nur vorhersehbare oder sinnvolle Ausgaben, wenn sie mit Textdateien arbeiten. Die Standarddienstprogramme, die solche Einschränkungen haben, geben in ihren STDIN- oder INPUT-FILES-Abschnitten immer "Textdateien" an.
Quelle: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397
Eine Zeichenkette als:
Eine zusammenhängende Folge von Bytes, die mit dem ersten Null-Byte endet und dieses einschließt.
Quelle: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396
Daraus können wir ableiten, dass die einzige Zeit, in der wir Möglicherweise Probleme auftauchen, sind, wenn wir uns mit dem Konzept eines Zeile einer Datei oder einer Datei als Textdatei (da ein Textdatei ist eine Organisation von null oder mehr Zeilen, und eine Zeile, von der wir wissen, dass sie mit einem <Newline> enden muss).
Ein typisches Beispiel: wc -l filename
.
De la wc
lesen wir im Handbuch:
Eine Zeile ist definiert als eine Zeichenfolge, die durch ein <Newline>-Zeichen begrenzt ist.
Was sind die Auswirkungen auf JavaScript-, HTML- und CSS-Dateien, da diese Text Dateien?
In Browsern, modernen IDEs und anderen Front-End-Anwendungen gibt es keine Probleme mit dem Überspringen von EOL bei EOF. Die Anwendungen parsen die Dateien ordnungsgemäß. Das muss sie auch, da nicht alle Betriebssysteme dem POSIX-Standard entsprechen, so dass es für Nicht-OS-Tools (z. B. Browser) unpraktisch wäre, Dateien nach dem POSIX-Standard (oder einem anderen Standard auf Betriebssystemebene) zu behandeln.
Daher können wir relativ sicher sein, dass EOL bei EOF praktisch keine negativen Auswirkungen auf die Anwendungsebene haben wird - unabhängig davon, ob sie auf einem UNIX-Betriebssystem läuft.
An diesem Punkt können wir getrost sagen, dass das Überspringen von EOL bei EOF sicher ist, wenn man mit JS, HTML, CSS auf der Client-Seite arbeitet. Tatsächlich können wir sagen, dass das Minifying jeder dieser Dateien, die keine <newline> enthält, sicher ist.
Wir können noch einen Schritt weiter gehen und sagen, dass sich auch NodeJS nicht an den POSIX-Standard halten kann, da es in nicht-POSIX-kompatiblen Umgebungen ausgeführt werden kann.
Was bleibt uns dann noch? Werkzeuge für die Systemebene.
Das bedeutet, dass die einzigen Probleme, die auftreten können, mit Werkzeugen zu tun haben, die sich bemühen, ihre Funktionalität an die Semantik von POSIX anzupassen (z.B. Definition einer Zeile, wie sie in wc
).
Dennoch halten sich nicht alle Shells automatisch an POSIX. Die Bash beispielsweise hält sich nicht standardmäßig an das POSIX-Verhalten. Es gibt einen Schalter, um es zu aktivieren: POSIXLY_CORRECT
.
Ein Denkanstoß über den Wert von EOL als <Newline>: https://www.rfc-editor.org/old/EOLstory.txt
Bleiben wir bei den Werkzeugen und betrachten wir dies für alle praktischen Zwecke:
Lassen Sie uns mit einer Datei arbeiten, die kein EOL hat. Zum Zeitpunkt dieses Schreibens ist die Datei in diesem Beispiel ein minifiziertes JavaScript ohne EOL.
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o x.js
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o y.js
$ cat x.js y.js > z.js
-rw-r--r-- 1 milanadamovsky 7905 Aug 14 23:17 x.js
-rw-r--r-- 1 milanadamovsky 7905 Aug 14 23:17 y.js
-rw-r--r-- 1 milanadamovsky 15810 Aug 14 23:18 z.js
Beachten Sie die cat
Die Dateigröße ist genau die Summe der einzelnen Teile. Wenn die Verkettung von JavaScript-Dateien ein Problem für JS-Dateien ist, wäre es sinnvoller, jede JavaScript-Datei mit einem Semikolon zu beginnen.
Wie jemand anderes in diesem Thread erwähnte: Was ist, wenn Sie cat
zwei Dateien, deren Ausgabe in einer einzigen Zeile statt in zwei Zeilen erfolgt? Mit anderen Worten, cat
tut, was es tun soll.
El man
de cat
erwähnt nur das Lesen von Eingaben bis zu EOF, nicht <Newline>. Beachten Sie, dass die -n
Wechsel von cat
gibt auch eine nicht mit <Newline> beendete Zeile aus (oder unvollständige Zeile ) als eine Zeile - wobei die Zählung bei 1 (nach der man
.)
-n Nummerierung der Ausgabezeilen, beginnend bei 1.
Nachdem wir nun verstanden haben, wie POSIX eine Zeile wird dieses Verhalten zweideutig oder tatsächlich nicht konform.
Das Verständnis des Zwecks eines bestimmten Tools und seiner Konformität hilft bei der Entscheidung, wie kritisch es ist, Dateien mit einem EOL zu beenden. In C, C++, Java (JARs) usw. schreiben einige Standards einen Zeilenumbruch für die Gültigkeit vor - für JS, HTML und CSS gibt es keinen solchen Standard.
Zum Beispiel, statt der Verwendung von wc -l filename
könnte man tun awk '{x++}END{ print x}' filename
und können sicher sein, dass der Erfolg der Aufgabe nicht durch eine Datei gefährdet wird, die wir nicht selbst geschrieben haben (z. B. eine Bibliothek eines Drittanbieters, wie das minifizierte JS, das wir curl
d) - es sei denn, unsere Absicht war wirklich zu zählen Zeilen im POSIX-konformen Sinne.
Schlussfolgerung
Es wird nur sehr wenige reale Anwendungsfälle geben, in denen das Überspringen von EOL bei EOF für bestimmte Textdateien wie JS, HTML und CSS negative Auswirkungen haben wird - wenn überhaupt. Wenn wir uns auf das Vorhandensein von <newline> verlassen, beschränken wir die Zuverlässigkeit unserer Werkzeuge nur auf die Dateien, die wir selbst erstellen, und öffnen uns für potenzielle Fehler, die durch Dateien von Dritten verursacht werden.
Die Moral von der Geschicht': Entwickeln Sie Werkzeuge, die nicht die Schwäche haben, sich auf EOL am EOF zu verlassen.
Fühlen Sie sich frei, Anwendungsfälle zu posten, die sich auf JS, HTML und CSS beziehen und in denen wir untersuchen können, wie sich das Überspringen von EOL negativ auswirkt.
Dies kann mit der Tatsache zusammenhängen, dass Unterschied zwischen :
- Textdatei (jede Zeile soll mit einem Zeilenende enden)
- Binärdatei (es gibt keine echten "Zeilen", und die Länge der Datei muss beibehalten werden)
Wenn jede Zeile mit einem Zeilenende endet, verhindert dies beispielsweise, dass bei der Verkettung zweier Textdateien die letzte Zeile der ersten in die erste Zeile der zweiten übergeht.
Außerdem kann ein Editor beim Laden prüfen, ob die Datei mit einem Zeilenende endet, es in seiner lokalen Option 'eol' speichern und diese beim Schreiben der Datei verwenden.
Vor ein paar Jahren (2005) haben viele Editoren (ZDE, Eclipse, Scite, ...) das endgültige EOL "vergessen", was nicht sehr gut ankam .
Nicht nur das, sondern sie interpretierten das letzte EOL fälschlicherweise als "Beginn einer neuen Zeile" und begannen tatsächlich, eine weitere Zeile anzuzeigen, als ob sie bereits existierte.
Dies war bei einer "richtigen" Textdatei mit einem gut funktionierenden Texteditor wie vim deutlich zu sehen, im Vergleich zum Öffnen in einem der oben genannten Editoren. Es wurde eine zusätzliche Zeile unter der eigentlichen letzten Zeile der Datei angezeigt. Sie sehen dann etwas wie das hier:
1 first line
2 middle line
3 last line
4
- See previous answers
- Weitere Antworten anzeigen