Was ist der Grund dafür, dass \ r und \ n verschiedene Dinge in s Befehl bedeuten?

13

Wir alle wissen, dass beim Suchen \nNewline und \rCarriage Return ( ^M) ist, beim Ersetzen \rNewline, während \nein Null-Byte ( ^@) ist.

Woher kommt diese Asymmetrie? Angesichts der Tatsache, dass dieses Verhalten ... gelinde gesagt ... eigentümlich ist (und ziemlich kontraproduktiv ist, wenn man es das erste Mal falsch macht), glaube ich, dass es einen bizarren historischen Grund gibt.

(Gibt es übrigens eine Möglichkeit, dieses Verhalten zu "beheben" und etwas intuitiver zu machen?)

Matteo Italia
quelle

Antworten:

10

Auf der grundlegendsten Ebene besteht bereits eine Asymmetrie zwischen dem Suchen und Ersetzen von Teilen, :substituteda ersterer ein regulärer Ausdruck und letzterer Text mit bestimmten zusätzlichen Escape-Sequenzen ist . Dies wird nur durch die Intuition hervorgehoben, die Sie darüber haben, was \nbedeutet.

Angenommen, \ndie Suche stimmt nicht mit einem Literal überein \n. Es stimmt mit dem Ende der Zeile (EOL) Bytefolge, die können \r, \r\noder einfach in \nAbhängigkeit von der 'fileformat'des Puffers.

Was \r"Einfügen einer EOL" betrifft, so steckt dahinter eine gewisse Geschichte . Vi hatte keine Möglichkeit, ein NUL-Byte in einer Datei zu verarbeiten. Vim verbesserte dies, indem intern NUL-Bytes durch NL-Bytes ersetzt wurden (da C-Strings durch NUL begrenzt sind).

Dieses Implementierungsdetail hat das Verhalten von verloren, :substituteda es \nbeim Ersetzen einfach in die interne Darstellung dieser Zeile eingefügt wird, die zum Anzeigen eines NUL-Bytes verwendet wird. \rFügt eine EOL ein und teilt die interne Linie in zwei Teile. Vim speichert die EOL-Bytes nicht im Speicher, sondern (de) serialisiert sie beim Lesen / Schreiben des Puffers.

Es kann jetzt nicht mehr geändert werden, ohne die vielen Skripte und das Muskelgedächtnis vieler Benutzer zu zerstören. Zum Glück ist es in dokumentiert :help sub-replace-special.

Jamessan
quelle
6

Ein NULByte ist ein Zeichenfolgenabschluss in C, und aus diesem Grund verwendet Vim diese Konvention, die im Handbuch unter :h NL-used-for-Nulfolgender Adresse beschrieben wird :

<Nul> -Zeichen in der Datei werden als <NL> im Speicher gespeichert. In der Anzeige werden sie als "^ @" angezeigt. Die Übersetzung erfolgt beim Lesen und Schreiben von Dateien. Um ein <Nul> mit einem Suchmuster abzugleichen, geben Sie einfach STRG- @ oder "STRG-V 000" ein. Dies ist wahrscheinlich genau das, was Sie erwarten. Intern wird das Zeichen im Suchmuster durch ein <NL> ersetzt. Was ungewöhnlich ist, ist, dass bei Eingabe von STRG-V STRG-J auch ein <NL> eingefügt wird und somit auch nach einem <Nul> in der Datei gesucht wird. {Vi kann überhaupt keine <Nul> -Zeichen in der Datei verarbeiten}

Diese Konvention wurde auf den :s/.../.../Befehl übertragen, nicht jedoch auf die substitute()Funktion. \rund \nin Ersetzungszeichenfolgen in substitute()Aufrufen behalten sie ihre ursprüngliche Bedeutung.

Ich glaube nicht, dass es tiefere Gründe für irgendein Verhalten gibt. Vim hat sich einfach organisch aus dem Original entwickelt vi. Es gab nie eine große Blaupause dafür, Features wurden einfach übereinander gestapelt, mit relativ geringem Aufwand, um sie zu organisieren.

Sato Katsura
quelle
0

Andere Vi-Klone unterstützen \roder \n(als echter Backslash und Buchstabe) keine Substitution, aber das Verhalten eines real ^M( CTRL-V Enter), das bedeutet, die Zeile in zwei Zeilen aufzuteilen, ist Standardverhalten :

Wenn Sie in repl ein <Wagenrücklaufzeichen> eingeben (das im ex- Modus ein Escapezeichen <Backslash> und im open- oder vi- Modus ein Escapezeichen <Control> -V erfordert ), wird die Zeile an dieser Stelle geteilt und eine neue Zeile im Bearbeitungspuffer erstellt . Der <Wagenrücklauf> wird verworfen.

Im Unix History-Archiv ist die erste Version von BSD ex / vi, in der es angezeigt wird, 4.1cBSD ( @(#)ex_re.c 7.2 10/16/81und ist in 4BSD ( @(#)ex_re.c 6.2 10/23/80) nicht vorhanden [4.1a und 4.1b sind nicht im Archiv vorhanden].

Der relevante Code lautet:

/* ^V <return> from vi to split lines */
if (c == '\r')
    c = '\n';

Dies wird auch in der Nachrichtendatei erwähnt :

Es ist jetzt möglich, Zeilen mit Ersatzbefehlen von vi zu trennen, indem ^ V <return> in rhs verwendet wird. Damit ist der letzte gute Grund für die Verwendung des ex-Befehlsmodus behoben.

Das zuvor unterstützte Verhalten im ex-Befehlsmodus war für Backslash-Enter (dh Backslash gefolgt von einer echten Newline), um eine Newline einzufügen.

Random832
quelle
0

Der Ursprung der Asymmetrie reicht bis in die Computergeschichte zurück.

Kurzfassung:

<CR> & <LF>  (Carriage-Return and Linefeed) 
== 
\r & \n

Lange Version:
Die ersten Bildschirme waren im Grunde digitale Versionen von Teletypen (TTY) und verwendeten Steuercodes, um ein ähnliches Verhalten wie Drucker zu erzeugen. Wagenrücklauf brachte den Cursor (oder Druckkopf) in die Startspalte. Der Zeilenvorschub rückte in die nächste Zeile (auf einem Bildschirm) vor und schob das Papier eine Zeile vor.

Bei Druckern mussten Sie eine Kopplung durchführen, da <CR><LF>sonst die Ausgabe nicht richtig aussah. Auf den ersten Bildschirmen galt das Problem immer noch.

DOS (und danach sorta-Windows) folgte dem alten Standard und speichert Text mit <CRLF>.

* NIX-Text (wie die meisten vi-Benutzer kennen) wird nur <LF>aus Effizienzgründen verwendet.

Verwenden Sie zum Testen in Windows Word / Wordpad und speichern Sie einige Textzeilen "als Typ: Text - MS-DOS-Format". Öffnen Sie dann dieselbe Datei in Editor. Es sollte normal aussehen. Speichern Sie dann dieselbe Datei in Word / Wordpad "als Typ: Text". Notepad ignoriert alle Zeilenumbrüche und führt die Zeilen zusammen aus. [Das Textformat von Notepad ist standardmäßig auf die \r\nKombination eingestellt, während Word / Wordpad standardmäßig auf \n.]

\ r ist das Code-Äquivalent von <CR>

\ n entspricht dem Code von <LF>

Und in meiner (sehr begrenzten) Erfahrung mit vi würde es versuchen, die <CRLF>Kombination aus meinem DOS-Texteditor zu "reparieren" . vi entfernte schließlich ein Zeichen und ersetzte es durch <NUL>. Ein großer Teil des Grundes, warum ich vi nicht mehr benutze.

Robin
quelle
2
Während alle Ihre Informationen interessant ist, sagt es nur , warum \rist <CR>und \nist <LF>. Es bezieht sich nicht auf die eigentliche Frage, warum \n\rverhalten sich unterschiedlich in unterschiedlichen Kontexten.
Tumbler41
Vielen Dank! :-) Ich habe es geändert, als du geantwortet hast. (Letzter Absatz hinzugefügt.)
Robin