Ich gehe davon aus, dass jeder hier mit dem Sprichwort vertraut ist, dass alle Textdateien mit einem Zeilenumbruch enden sollten. Ich kenne diese "Regel" seit Jahren, habe mich aber immer gefragt - warum?
Ich gehe davon aus, dass jeder hier mit dem Sprichwort vertraut ist, dass alle Textdateien mit einem Zeilenumbruch enden sollten. Ich kenne diese "Regel" seit Jahren, habe mich aber immer gefragt - warum?
Antworten:
Denn so definiert der POSIX-Standard eine Linie :
- 3.206 Linie
- Eine Folge von null oder mehr Nicht-<newline> -Zeichen plus einem abschließenden <newline> -Zeichen.
Daher werden Zeilen, die nicht mit einem Zeilenumbruchzeichen enden, nicht als tatsächliche Zeilen betrachtet. Aus diesem Grund haben einige Programme Probleme, die letzte Zeile einer Datei zu verarbeiten, wenn sie nicht beendet ist.
Diese Richtlinie bietet mindestens einen entscheidenden Vorteil bei der Arbeit an einem Terminalemulator: Alle Unix-Tools erwarten diese Konvention und arbeiten damit. Wenn Sie beispielsweise Dateien mit verketten cat
, hat eine durch newline beendete Datei einen anderen Effekt als eine ohne:
$ more a.txt
foo
$ more b.txt
bar$ more c.txt
baz
$ cat {a,b,c}.txt
foo
barbaz
Und wie das vorherige Beispiel auch zeigt, führt eine Datei mit Zeilenumbruch bei der Anzeige der Datei in der Befehlszeile (z. B. über more
) zu einer korrekten Anzeige. Eine nicht ordnungsgemäß terminierte Datei ist möglicherweise verstümmelt (zweite Zeile).
Aus Gründen der Konsistenz ist es sehr hilfreich, diese Regel zu befolgen. Andernfalls ist beim Umgang mit den Standard-Unix-Tools zusätzliche Arbeit erforderlich.
Stellen Sie sich das anders vor: Wenn Zeilen nicht durch Zeilenumbrüche abgeschlossen werden, ist cat
es viel schwieriger , Befehle wie nützlich zu machen: Wie erstellen Sie einen Befehl, um Dateien so zu verketten, dass
b.txt
und c.txt
?Natürlich ist dies lösbar, aber Sie müssen die Verwendung cat
komplexer gestalten (z. B. durch Hinzufügen von Positionsbefehlszeilenargumenten cat a.txt --no-newline b.txt c.txt
), und jetzt steuert der Befehl anstelle jeder einzelnen Datei, wie er zusammen mit anderen Dateien eingefügt wird. Dies ist mit ziemlicher Sicherheit nicht bequem.
… Oder Sie müssen ein spezielles Sentinel-Zeichen einführen, um eine Zeile zu markieren, die fortgesetzt und nicht beendet werden soll. Nun, jetzt stecken Sie in der gleichen Situation wie unter POSIX, außer invertiert (Zeilenfortsetzung statt Zeilenabschlusszeichen).
Auf nicht POSIX-kompatiblen Systemen (heutzutage meistens Windows) ist der Punkt umstritten: Dateien enden im Allgemeinen nicht mit einer neuen Zeile, und die (informelle) Definition einer Zeile kann beispielsweise " durch Zeilenumbrüche getrennter Text" sein. (Beachten Sie die Betonung). Dies ist völlig gültig. Für strukturierte Daten (z. B. Programmcode) wird das Parsen jedoch minimal komplizierter: Im Allgemeinen müssen Parser neu geschrieben werden. Wenn ein Parser ursprünglich unter Berücksichtigung der POSIX-Definition geschrieben wurde, ist es möglicherweise einfacher, den Token-Stream als den Parser zu ändern. Mit anderen Worten, fügen Sie am Ende der Eingabe ein Token mit „künstlicher Zeilenumbruch“ hinzu.
cat
auf nützliche und konsistente Weise.
Jede Zeile sollte mit einem Zeilenumbruchzeichen abgeschlossen werden, einschließlich des letzten. Einige Programme haben Probleme beim Verarbeiten der letzten Zeile einer Datei, wenn diese nicht beendet ist.
GCC warnt vor ihm nicht , weil es nicht kann , die Datei verarbeiten, sondern weil es muss als Teil des Standard.
Der C-Sprachstandard besagt, dass eine Quelldatei, die nicht leer ist, mit einem Zeilenumbruchzeichen enden darf, dem nicht unmittelbar ein Backslash-Zeichen vorangestellt werden darf.
Da dies eine "soll" -Klausel ist, müssen wir eine Diagnosemeldung für einen Verstoß gegen diese Regel ausgeben.
Dies ist in Abschnitt 2.1.1.2 des ANSI C 1989-Standards enthalten. Abschnitt 5.1.1.2 der Norm ISO C 1999 (und wahrscheinlich auch der Norm ISO C 1990).
Referenz: Das GCC / GNU-Mail-Archiv .
wc -l
zählt die letzte Zeile einer Datei nicht, wenn sie nicht beendet ist. Auch cat
beitreten die letzte Zeile einer Datei mit der ersten Zeile der nächsten Datei in ein , wenn die letzte Zeile der ersten Datei nicht Newline beendet. So ziemlich jedes Programm, das nach Zeilenumbrüchen als Trennzeichen sucht, hat das Potenzial, dies durcheinander zu bringen.
wc
wurde bereits erwähnt ....
cat
und massenweise erwähnt wurden wc
)?
Diese Antwort ist eher ein Versuch einer technischen Antwort als eine Meinung.
Wenn wir POSIX-Puristen sein wollen, definieren wir eine Linie 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 keines darf die Länge von {LINE_MAX} Bytes überschreiten, einschließlich des Zeichens <newline>. Obwohl POSIX.1-2008 nicht zwischen Textdateien und Binärdateien unterscheidet (siehe ISO C-Standard), erzeugen viele Dienstprogramme nur vorhersehbare oder aussagekräftige Ausgaben, wenn sie mit Textdateien arbeiten. Die Standarddienstprogramme mit solchen Einschränkungen geben in ihren Abschnitten STDIN oder INPUT FILES immer "Textdateien" an.
Quelle: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397
Eine Zeichenfolge als:
Eine zusammenhängende Folge von Bytes, die mit dem ersten Nullbyte abgeschlossen sind und dieses enthalten.
Quelle: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396
Daraus können wir ableiten, dass wir möglicherweise nur dann auf Probleme stoßen, wenn wir uns mit dem Konzept einer Zeile einer Datei oder einer Datei als Textdatei befassen (dh, eine Textdatei ist eine Organisation von Null) oder mehr Zeilen, und eine Zeile, die wir kennen, muss mit einer <neuen Zeile>) enden.
Ein typisches Beispiel : wc -l filename
.
Aus dem wc
Handbuch lesen wir:
Eine Zeile ist definiert als eine Zeichenfolge, die durch ein <neues> Zeichen begrenzt wird.
Was sind die Auswirkungen auf JavaScript, HTML und CSS - Dateien dann sein , dass sie Text - Dateien?
In Browsern, modernen IDEs und anderen Front-End-Anwendungen gibt es keine Probleme beim Überspringen von EOL bei EOF. Die Anwendungen analysieren die Dateien ordnungsgemäß. Da nicht alle Betriebssysteme dem POSIX-Standard entsprechen müssen, ist es für Nicht-Betriebssystem-Tools (z. B. Browser) unpraktisch, Dateien gemäß dem POSIX-Standard (oder einem beliebigen Standard auf Betriebssystemebene) zu verarbeiten.
Infolgedessen können wir relativ sicher sein, dass EOL bei EOF auf Anwendungsebene praktisch keine negativen Auswirkungen hat - unabhängig davon, ob es unter einem UNIX-Betriebssystem ausgeführt wird.
An dieser Stelle können wir mit Sicherheit sagen, dass das Überspringen von EOL bei EOF sicher ist, wenn auf der Clientseite mit JS, HTML, CSS gearbeitet wird. Tatsächlich können wir feststellen, dass das Minimieren einer dieser Dateien, die keine <newline> enthalten, sicher ist.
Wir können noch einen Schritt weiter gehen und sagen, dass NodeJS auch den POSIX-Standard nicht einhalten kann, da es in nicht POSIX-kompatiblen Umgebungen ausgeführt werden kann.
Was bleibt uns dann übrig? Werkzeuge auf Systemebene.
Dies bedeutet, dass nur Probleme mit Tools auftreten können, die sich bemühen, ihre Funktionalität an die Semantik von POSIX anzupassen (z. B. Definition einer Linie wie in gezeigt wc
).
Trotzdem haften nicht alle Shells automatisch an POSIX. Bash verwendet beispielsweise nicht standardmäßig das POSIX-Verhalten. Es gibt einen Schalter, um es zu aktivieren : POSIXLY_CORRECT
.
Denkanstöße zum Wert von EOL als <newline>: https://www.rfc-editor.org/old/EOLstory.txt
Lassen Sie uns Folgendes in Betracht ziehen, um auf der Werkzeugspur zu bleiben:
Lassen Sie uns mit einer Datei arbeiten, die keine EOL hat. Zum jetzigen Zeitpunkt ist die Datei in diesem Beispiel ein minimiertes 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, dass die cat
Dateigröße genau die Summe der einzelnen Teile ist. Wenn die Verkettung von JavaScript-Dateien ein Problem für JS-Dateien darstellt, ist es besser, jede JavaScript-Datei mit einem Semikolon zu starten.
Wie jemand anderes in diesem Thread erwähnt hat: Was ist, wenn Sie cat
zwei Dateien möchten, deren Ausgabe nur eine Zeile statt zwei ist? Mit anderen Worten, cat
tut, was es tun soll.
Das man
von cat
erwähnt nur das Lesen von Eingaben bis zu EOF, nicht <newline>. Beachten Sie, dass beim -n
Umschalten von cat
auch eine nicht <newline> terminierte Zeile (oder unvollständige Zeile ) als Zeile ausgedruckt wird - dh , die Zählung beginnt bei 1 (gemäß man
.).
-n Nummerieren Sie die Ausgangsleitungen beginnend mit 1.
Nachdem wir nun verstanden haben, wie POSIX eine Linie definiert , wird dieses Verhalten mehrdeutig oder nicht mehr konform.
Wenn Sie den Zweck und die Konformität eines bestimmten Tools verstehen, können Sie feststellen, wie wichtig es ist, Dateien mit einer EOL zu beenden. In C, C ++, Java (JARs) usw. schreiben einige Standards eine neue Zeile für die Gültigkeit vor - für JS, HTML, CSS gibt es keinen solchen Standard.
Anstatt beispielsweise wc -l filename
eine zu verwenden awk '{x++}END{ print x}' filename
, können Sie sicher sein, dass der Erfolg der Aufgabe nicht durch eine Datei gefährdet wird, die wir möglicherweise verarbeiten möchten, die wir nicht geschrieben haben (z. B. eine Drittanbieter-Bibliothek wie die minimierte JS, die wir erstellt haben curl
) - es sei denn, unsere Die Absicht war wirklich, Zeilen im POSIX-konformen Sinne zu zählen.
Fazit
Es wird nur sehr wenige reale Anwendungsfälle geben, in denen sich das Überspringen von EOL bei EOF für bestimmte Textdateien wie JS, HTML und CSS - wenn überhaupt - negativ auswirkt. Wenn wir uns darauf verlassen, dass <newline> vorhanden ist, beschränken wir die Zuverlässigkeit unserer Werkzeuge nur auf die Dateien, die wir erstellen, und öffnen uns potenziellen Fehlern, die durch Dateien von Drittanbietern verursacht werden.
Moral der Geschichte: Ingenieurwerkzeuge, die nicht die Schwäche haben, sich bei EOF auf EOL zu verlassen.
Sie können gerne Anwendungsfälle für JS, HTML und CSS veröffentlichen, in denen wir untersuchen können, wie sich das Überspringen von EOL nachteilig auswirkt.
Es kann mit dem Unterschied zusammenhängen zwischen :
Wenn jede Zeile mit einem Zeilenende endet, wird beispielsweise vermieden, dass durch die Verkettung von zwei Textdateien die letzte Zeile der ersten Zeile in die erste Zeile der zweiten Zeile übergeht.
Außerdem kann ein Editor beim Laden prüfen, ob die Datei am Zeilenende endet, sie in der lokalen Option 'eol' speichern und beim Schreiben der Datei verwenden.
Vor einigen Jahren (2005) haben viele Redakteure (ZDE, Eclipse, Scite, ...) diese endgültige EOL "vergessen", was nicht sehr geschätzt wurde .
Nicht nur das, sondern sie interpretierten diese endgültige EOL falsch als "Neue Zeile beginnen" und zeigen tatsächlich eine andere Zeile an, als ob sie bereits vorhanden wäre.
Dies war bei einer 'richtigen' Textdatei mit einem gut erzogenen Texteditor wie vim sehr gut sichtbar, verglichen mit dem Öffnen in einem der oben genannten Editoren. Es wurde eine zusätzliche Zeile unter der letzten Zeile der Datei angezeigt. Sie sehen so etwas:
1 first line
2 middle line
3 last line
4
Einige Tools erwarten dies. Erwartet zum Beispiel wc
Folgendes:
$ echo -n "Line not ending in a new line" | wc -l
0
$ echo "Line ending with a new line" | wc -l
1
wc
dies nicht erwartet wird, da es einfach innerhalb der POSIX-Definition einer "Linie" funktioniert, im Gegensatz zum intuitiven Verständnis der meisten Leute von "Linie".
wc -l
zu drucken 1
, aber einige Leute könnten sagen, der zweite Fall sollte gedruckt werden 2
.
\n
als Zeilenabschluss und nicht als Zeilentrennzeichen vorstellen, wie es POSIX / UNIX tut, ist es absolut verrückt, zu erwarten, dass der zweite Fall 2 druckt.
Grundsätzlich gibt es viele Programme, die Dateien nicht korrekt verarbeiten, wenn sie nicht die endgültige EOL EOF erhalten.
GCC warnt Sie davor, da dies als Teil des C-Standards erwartet wird. (Abschnitt 5.1.1.2 anscheinend)
Dies stammt aus den frühen Tagen, als einfache Terminals verwendet wurden. Das Zeilenumbruchzeichen wurde verwendet, um ein "Flush" der übertragenen Daten auszulösen.
Heute wird das Newline-Zeichen nicht mehr benötigt. Sicher, viele Apps haben immer noch Probleme, wenn der Zeilenumbruch nicht vorhanden ist, aber ich würde das als Fehler in diesen Apps betrachten.
Wenn Sie jedoch ein Textdateiformat haben, in dem Sie die neue Zeile benötigen , erhalten Sie eine einfache Datenüberprüfung sehr günstig: Wenn die Datei mit einer Zeile endet, die am Ende keine neue Zeile enthält, wissen Sie, dass die Datei fehlerhaft ist. Mit nur einem zusätzlichen Byte pro Zeile können Sie fehlerhafte Dateien mit hoher Genauigkeit und fast ohne CPU-Zeit erkennen.
Ein separater Anwendungsfall: Wenn Ihre Textdatei versioniert ist (in diesem Fall speziell unter Git, obwohl dies auch für andere gilt). Wenn am Ende der Datei Inhalt hinzugefügt wird, wurde die Zeile, die zuvor die letzte Zeile war, so bearbeitet, dass sie ein Zeilenumbruchzeichen enthält. Dies bedeutet, dass in blame
der Datei, um herauszufinden, wann diese Zeile zuletzt bearbeitet wurde, der Textzusatz und nicht das Commit angezeigt wird, das Sie tatsächlich sehen wollten.
\n
). Problem gelöst.
Zusätzlich zu den oben genannten praktischen Gründen würde es mich nicht wundern, wenn die Urheber von Unix (Thompson, Ritchie et al.) Oder ihre Multics-Vorgänger erkennen würden, dass es einen theoretischen Grund gibt, Zeilenabschlusszeichen anstelle von Zeilenabscheidern zu verwenden: Mit Zeile Terminatoren können Sie alle möglichen Dateien von Zeilen codieren. Bei Zeilentrennzeichen gibt es keinen Unterschied zwischen einer Datei mit null Zeilen und einer Datei mit einer einzelnen leeren Zeile. Beide sind als Datei mit null Zeichen codiert.
Die Gründe sind also:
wc -l
Zählt beispielsweise keine letzte "Zeile", wenn sie nicht mit einer neuen Zeile endet.cat
funktioniert es einfach und es funktioniert ohne Komplikationen. Es werden nur die Bytes jeder Datei kopiert, ohne dass eine Interpretation erforderlich ist. Ich glaube nicht, dass es ein DOS-Äquivalent zu gibt cat
. Mit copy a+b c
wird die letzte Dateizeile a
mit der ersten Dateizeile zusammengeführt b
.Ich habe mich das jahrelang selbst gefragt. Aber ich bin heute auf einen guten Grund gestoßen.
Stellen Sie sich eine Datei mit einem Datensatz in jeder Zeile vor (z. B. eine CSV-Datei). Und dass der Computer am Ende der Datei Aufzeichnungen schrieb. Aber es stürzte plötzlich ab. Gee war die letzte Zeile komplett? (keine schöne Situation)
Wenn wir jedoch immer die letzte Zeile beenden, wissen wir es (überprüfen Sie einfach, ob die letzte Zeile beendet ist). Andernfalls müssten wir wahrscheinlich jedes Mal die letzte Zeile verwerfen, nur um sicher zu gehen.
Vermutlich einfach, dass irgendein Parsing-Code damit gerechnet hat.
Ich bin mir nicht sicher, ob ich es als "Regel" betrachten würde, und es ist sicherlich nichts, woran ich mich religiös halte. Der sinnvollste Code kann Text (einschließlich Codierungen) zeilenweise (beliebige Zeilenenden) mit oder ohne Zeilenumbruch in der letzten Zeile analysieren.
In der Tat - wenn Sie mit einer neuen Zeile enden: Gibt es (theoretisch) eine leere letzte Zeile zwischen der EOL und der EOF? Einer zum Nachdenken ...
Es gibt auch ein praktisches Programmierproblem mit Dateien, denen am Ende Zeilenumbrüche fehlen: Der integrierte read
Bash (ich weiß nichts über andere read
Implementierungen) funktioniert nicht wie erwartet:
printf $'foo\nbar' | while read line
do
echo $line
done
Dies druckt nurfoo
! Der Grund dafür ist, dass beim read
Aufrufen der letzten Zeile der Inhalt in den $line
Exit-Code 1 geschrieben wird, dieser jedoch zurückgegeben wird, da er EOF erreicht hat. Dies unterbricht die while
Schleife, sodass wir das echo $line
Teil nie erreichen . Wenn Sie mit dieser Situation umgehen möchten, müssen Sie Folgendes tun:
while read line || [ -n "${line-}" ]
do
echo $line
done < <(printf $'foo\nbar')
Führen Sie das aus, echo
wenn dies read
aufgrund einer nicht leeren Zeile am Ende der Datei fehlgeschlagen ist. In diesem Fall gibt es natürlich eine zusätzliche neue Zeile in der Ausgabe, die nicht in der Eingabe enthalten war.
Warum sollten (Text-) Dateien mit einem Zeilenumbruch enden?
Auch von vielen ausgedrückt, weil:
Viele Programme verhalten sich nicht gut oder schlagen ohne fehl.
Selbst Programme, die eine Datei gut verarbeiten, haben kein Ende '\n'
. Die Funktionalität des Tools entspricht möglicherweise nicht den Erwartungen des Benutzers - was in diesem Eckfall unklar sein kann.
Programme verbieten Final selten '\n'
(ich kenne keine).
Dies wirft jedoch die nächste Frage auf:
Was sollte Code mit Textdateien ohne Zeilenumbruch tun?
Am wichtigsten - Schreiben Sie keinen Code, der davon ausgeht, dass eine Textdatei mit einem Zeilenumbruch endet . Die Annahme, dass eine Datei einem Format entspricht, führt zu Datenbeschädigung, Hackerangriffen und Abstürzen. Beispiel:
// Bad code
while (fgets(buf, sizeof buf, instream)) {
// What happens if there is no \n, buf[] is truncated leading to who knows what
buf[strlen(buf) - 1] = '\0'; // attempt to rid trailing \n
...
}
Wenn die letzte Nachverfolgung '\n'
erforderlich ist, machen Sie den Benutzer auf seine Abwesenheit und die ergriffenen Maßnahmen aufmerksam. IOWs, überprüfen Sie das Dateiformat. Hinweis: Dies kann eine Begrenzung der maximalen Zeilenlänge, Zeichencodierung usw. beinhalten.
Definieren Sie klar und deutlich, wie der Code mit einem fehlenden Finale umgeht '\n'
.
Generieren Sie nach Möglichkeit keine Datei, der das Ende fehlt '\n'
.
Es ist sehr spät hier, aber ich hatte nur einen Fehler in der Dateiverarbeitung und der kam, weil die Dateien nicht mit einem leeren Zeilenumbruch endeten. Wir haben Textdateien mit verarbeitet sed
und sed
die letzte Zeile in der Ausgabe weggelassen, was zu einer ungültigen JSON-Struktur führte und den Rest des Prozesses zum Fehlschlagen brachte.
Alles was wir machten war:
Es gibt eine Beispieldatei, die sagt: foo.txt
mit etwas json
Inhalt darin.
[{
someProp: value
},
{
someProp: value
}] <-- No newline here
Die Datei wurde auf einem Witwencomputer erstellt, und Fensterskripte verarbeiteten diese Datei mit PowerShell-Befehlen. Alles gut.
Wenn wir dieselbe Datei mit dem sed
Befehl verarbeitet habensed 's|value|newValue|g' foo.txt > foo.txt.tmp
Die neu generierte Datei war
[{
someProp: value
},
{
someProp: value
und Boom, es schlug der Rest der Prozesse wegen des ungültigen JSON fehl.
Es ist daher immer eine gute Praxis, Ihre Datei mit einer leeren neuen Zeile zu beenden.
Ich hatte immer den Eindruck, dass die Regel aus den Tagen stammte, als es schwierig war, eine Datei ohne endenden Zeilenumbruch zu analysieren. Das heißt, Sie würden am Ende Code schreiben, bei dem ein Zeilenende durch das EOL-Zeichen oder EOF definiert wurde. Es war einfach einfacher anzunehmen, dass eine Zeile mit EOL endete.
Ich glaube jedoch, dass die Regel von C-Compilern abgeleitet ist, die die Newline benötigen. Und wie in der Compiler-Warnung "Keine neue Zeile am Ende der Datei" angegeben , fügt #include keine neue Zeile hinzu.
Stellen Sie sich vor, die Datei wird verarbeitet, während die Datei noch von einem anderen Prozess generiert wird.
Es könnte damit zu tun haben? Ein Flag, das angibt, dass die Datei zur Verarbeitung bereit ist.
Ich persönlich mag neue Zeilen am Ende von Quellcodedateien.
Es kann seinen Ursprung in Linux oder allen UNIX-Systemen haben. Ich erinnere mich an Kompilierungsfehler (gcc, wenn ich mich nicht irre), weil Quellcodedateien nicht mit einer leeren neuen Zeile endeten. Warum es so gemacht wurde, muss man sich fragen.
IMHO, es ist eine Frage des persönlichen Stils und der Meinung.
In alten Tagen habe ich diese Newline nicht gesetzt. Ein gespeicherter Charakter bedeutet mehr Geschwindigkeit durch dieses 14,4-KB-Modem.
Später habe ich diese neue Zeile eingefügt, damit es einfacher ist, die letzte Zeile mit Umschalt + Abwärtspfeil auszuwählen.