Was ist der Unterschied zwischen \ r und \ n?


245

Wie sind \rund \nanders? Ich denke, es hat etwas mit Unix vs. Windows vs. Mac zu tun, aber ich bin mir nicht sicher, wie genau sie sich unterscheiden und welche Regexe gesucht / gefunden werden sollen.


1
Dies benötigt ein Sprach-Tag. Unterschiedliche Sprachen haben unterschiedliche Interpretationen von '\n'.
Adrian McCarthy

Antworten:


383

Sie sind verschiedene Charaktere. \rist Wagenrücklauf und \nist Zeilenvorschub.

\rSenden Sie auf "alten" Druckern den Druckkopf zurück zum Zeilenanfang und \nschieben Sie das Papier um eine Zeile vor. Beide waren daher erforderlich, um mit dem Drucken in der nächsten Zeile zu beginnen.

Offensichtlich ist das jetzt etwas irrelevant, obwohl Sie je nach Konsole möglicherweise immer noch in der Lage sind, \rzum Zeilenanfang zu wechseln und den vorhandenen Text zu überschreiben.

Noch wichtiger ist, dass Unix in der Regel \nals Trennzeichen verwendet wird. Fenster dazu neigen , zu verwenden \r\nals eine Linie Separator und Mac (bis O 9) verwendet , verwenden , \rwie die Linie Separator. (Mac OS X ist Unix-y und wird \nstattdessen verwendet. Es kann einige Kompatibilitätssituationen geben, in denen\r stattdessen verwendet wird.)

Weitere Informationen finden Sie im Wikipedia-Artikel .

EDIT: Dies ist sprachempfindlich. In C # und Java bedeutet dies beispielsweise \n immer Unicode U + 000A, das als Zeilenvorschub definiert ist. In C und C ++ ist das Wasser etwas matschiger, da die Bedeutung plattformspezifisch ist. Siehe Kommentare für Details.


22
+1 für alte Leute. Terminalausgang zur direkten Steuerung eines verherrlichten elektronischen Terminals (Ihr TTY vor diesen ausgefallenen CRT-Anzeigen). Daher erhalten wir wunderbare Artefakte von Personen in den Wagenrücklauf- und Zeilenumbruchzeichen (die beide möglicherweise benötigt werden, wie Jon Skeet erwähnte) und Dinge wie "eine" Glocke "," b "Rücktaste" (nicht zu verwechseln mit "Löschen") ") und alle anderen Steuerzeichen, die für die Kommunikation mit einem tty benötigt werden.
Erjiang

35
Noch eine +1 für alte Leute. Sie können weiterhin an einer Windows-Eingabeaufforderung Strg + G drücken, die Eingabetaste drücken und der PC-Lautsprecher piept. Das ist aus alten Zeiten übrig geblieben.
Dave Carlile

@Crappy Coding Guy wirklich? Unter Vista heißt es nur "'' wird nicht als interner oder externer Befehl erkannt"
Ponkadoodle

2
@AdrianMcCarthy: Natürlich ist die Frage eigentlich nicht angeben C oder C ++ hier. In C #, zum Beispiel \n wird garantiert Newline sein (siehe Abschnitt 2.4.4.4). Natürlich wäre es schön, wenn das OP die Plattform spezifiziert hätte ... Außerdem denke ich, dass dieser Detaillierungsgrad für jemanden, der nur nach dem Unterschied fragt, eher verwirrend als nützlich wäre.
Jon Skeet

2
@AdrianMcCarthy: Aber in C # und Java zumindest, es ist Zeilenvorschub. Es ist U + 000A, das von Unicode als "LINE FEED" (und NEW LINE) bezeichnet wird. Ich werde bearbeiten den speziellen Fall von C und C ++ zu erwähnen, aber ich glaube wirklich diejenigen sind Sonderfälle, nicht umgekehrt.
Jon Skeet

91

In C und C ++ \nist es ein Konzept, \rein Charakter und \r\n(fast immer) ein Portabilitätsfehler.

Denken Sie an einen alten Fernschreiber. Der Druckkopf befindet sich in einer Zeile und in einer Spalte. Wenn Sie ein druckbares Zeichen an den Teletyp senden, wird das Zeichen an der aktuellen Position gedruckt und der Kopf in die nächste Spalte verschoben. (Dies ist konzeptionell dasselbe wie eine Schreibmaschine, außer dass Schreibmaschinen das Papier normalerweise in Bezug auf den Druckkopf bewegen.)

Wenn Sie die aktuelle Zeile beenden und mit der nächsten Zeile beginnen wollten, mussten Sie zwei separate Schritte ausführen:

  1. Bewegen Sie den Druckkopf dann zurück zum Zeilenanfang
  2. Bewegen Sie es nach unten in die nächste Zeile.

ASCII codiert diese Aktionen als zwei unterschiedliche Steuerzeichen:

  • \x0D(CR) bewegt den Druckkopf zurück zum Zeilenanfang. (Unicode codiert dies als U+000D CARRIAGE RETURN.)
  • \x0A(LF) bewegt den Druckkopf nach unten in die nächste Zeile. (Unicode codiert dies als U+000A LINE FEED.)

In den Tagen von Teletypen und frühen Technologiedruckern nutzten die Menschen tatsächlich die Tatsache, dass dies zwei getrennte Operationen waren. Wenn Sie eine CR senden, ohne ihr von einem LF zu folgen, können Sie über die bereits gedruckte Zeile drucken. Dies ermöglichte Effekte wie Akzente, Fettdruck und Unterstreichung. Einige Systeme wurden mehrmals überdruckt, um zu verhindern, dass Kennwörter in Papierform angezeigt werden. Bei frühen seriellen CRT-Terminals war CR eine der Möglichkeiten, die Cursorposition zu steuern, um bereits auf dem Bildschirm angezeigten Text zu aktualisieren.

Aber die meiste Zeit wollten Sie eigentlich nur zur nächsten Zeile gehen. Anstatt das Paar von Steuerzeichen zu benötigen, erlaubten einige Systeme nur das eine oder andere. Beispielsweise:

  • Unix-Varianten (einschließlich moderner Mac-Versionen) verwenden nur ein LF-Zeichen, um eine neue Zeile anzuzeigen.
  • Alte Macintosh-Dateien (vor OSX) verwendeten nur ein CR-Zeichen, um eine neue Zeile anzuzeigen.
  • VMS, CP / M, DOS, Windows und viele Netzwerkprotokolle erwarten immer noch beides: CR LF.
  • Alte IBM Systeme, die EBCDIC verwendet haben, sind auf NL standardisiert - ein Zeichen, das im ASCII-Zeichensatz nicht einmal vorhanden ist. In Unicode ist NL U+0085 NEXT LINE, aber der tatsächliche EBCDIC-Wert ist 0x15.

Warum haben verschiedene Systeme unterschiedliche Methoden gewählt? Einfach weil es keinen universellen Standard gab. Wo Ihre Tastatur wahrscheinlich "Enter" anzeigt, sagten ältere Tastaturen "Return", was für Carriage Return kurz war. Wenn Sie auf einem seriellen Terminal die Eingabetaste drücken, wird das CR-Zeichen gesendet. Wenn Sie einen Texteditor schreiben, wäre es verlockend, nur dieses Zeichen zu verwenden, wenn es vom Terminal eingeht. Vielleicht haben die älteren Macs deshalb nur CR verwendet.

Jetzt, da wir Standards haben , gibt es mehr Möglichkeiten, Zeilenumbrüche darzustellen. Obwohl Unicode in freier Wildbahn äußerst selten ist, hat es neue Charaktere wie:

  • U+2028 LINE SEPARATOR
  • U+2029 PARAGRAPH SEPARATOR

Noch bevor Unicode auf den Markt kam, wollten Programmierer auf einfache Weise einige der nützlichsten Steuercodes darstellen, ohne sich um den zugrunde liegenden Zeichensatz kümmern zu müssen. C hat mehrere Escape-Sequenzen zur Darstellung von Steuercodes:

  • \a (für Alarm), der die Teletyp-Klingel läutet oder das Terminal piepen lässt
  • \f (für Formularvorschub), der zum Anfang der nächsten Seite wechselt
  • \t (für Tabulator), der den Druckkopf zur nächsten horizontalen Tabulatorposition bewegt

(Diese Liste ist absichtlich unvollständig.)

Diese Zuordnung erfolgt zur Kompilierungszeit - der Compiler sieht \aund setzt den magischen Wert, der zum Klingeln verwendet wird.

Beachten Sie, dass die meisten dieser Mnemoniken direkte Korrelationen zu ASCII-Steuercodes aufweisen. Zum Beispiel \awürde zuordnen 0x07 BEL. Ein Compiler könnte für ein System geschrieben werden, das etwas anderes als ASCII für den Host-Zeichensatz verwendet (z. B. EBCDIC). Die meisten Steuercodes mit bestimmten Mnemoniken konnten Steuercodes in anderen Zeichensätzen zugeordnet werden.

Huzzah! Portabilität!

Naja fast. In C könnte ich schreiben, printf("\aHello, World!");was klingelt (oder piept) und eine Nachricht ausgibt. Aber wenn ich dann etwas in der nächsten Zeile drucken wollte, musste ich immer noch wissen, was die Host-Plattform benötigt, um zur nächsten Ausgabezeile zu wechseln. CR LF? CR? LF? NL? Etwas anderes? Soviel zur Portabilität.

C hat zwei Modi für E / A: Binär und Text. Im Binärmodus werden alle gesendeten Daten unverändert übertragen. Im Textmodus gibt es jedoch eine Laufzeitübersetzung , die ein Sonderzeichen in das konvertiert, was die Hostplattform für eine neue Zeile benötigt (und umgekehrt).

Großartig, was ist der besondere Charakter?

Nun, das hängt auch von der Implementierung ab, aber es gibt eine implementierungsunabhängige Möglichkeit, dies anzugeben : \n. Es wird normalerweise als "Zeilenumbruch" bezeichnet.

Dies ist ein subtiler, aber wichtiger Punkt: \n Wird zur Kompilierungszeit einem implementierungsdefinierten Zeichenwert zugeordnet , der (im Textmodus) zur Laufzeit erneut dem tatsächlichen Zeichen (oder der Zeichenfolge) zugeordnet wird, das von der zugrunde liegenden Plattform zum Verschieben benötigt wird zur nächsten Zeile.

\nunterscheidet sich von allen anderen Backslash-Literalen, da zwei Zuordnungen beteiligt sind. Diese zweistufige Zuordnung \nunterscheidet sich erheblich von der geraden Zuordnung \r, bei der es sich lediglich um eine Zuordnung zur Kompilierungszeit zu CR handelt (oder um den ähnlichsten Steuercode in dem zugrunde liegenden Zeichensatz).

Dies löst viele C- und C ++ - Programmierer aus. Wenn Sie 100 von ihnen abfragen, sagen Ihnen mindestens 99, dass \ndies Zeilenvorschub bedeutet. Dies ist nicht ganz richtig. Die meisten (vielleicht alle) C- und C ++ - Implementierungen verwenden LF als magischen Zwischenwert für \n, aber das ist ein Implementierungsdetail. Für einen Compiler ist es möglich, einen anderen Wert zu verwenden. Wenn der Host-Zeichensatz keine Obermenge von ASCII ist (z. B. wenn es sich um EBCDIC handelt), ist er \nmit ziemlicher Sicherheit kein LF.

Also, in C und C ++:

  • \r ist buchstäblich ein Wagenrücklauf.
  • \nist ein magischer Wert, der zur Laufzeit (im Textmodus) in die Newline-Semantik der Host-Plattform übersetzt wird.
  • \r\nist fast immer ein Portabilitätsfehler. Im Textmodus wird dies in CR übersetzt, gefolgt von der Zeilenumbruchsequenz der Plattform - wahrscheinlich nicht das, was beabsichtigt ist. Im Binärmodus wird dies in CR übersetzt, gefolgt von einem magischen Wert, der möglicherweise nicht LF ist - möglicherweise nicht das, was beabsichtigt ist.
  • \x0Aist die portabelste Methode, um einen ASCII-LF anzuzeigen, aber Sie möchten dies nur im Binärmodus tun. Die meisten Implementierungen im Textmodus behandeln dies wie folgt \n.

Kam über diesen Beitrag, als ich versuchte herauszufinden, wie man <textarea> -Eingaben in Python aufteilt, und \r\nist eigentlich die einzige Möglichkeit, die Zeilen richtig in separate Listenelemente aufzuteilen. Ich frage mich, ob dies ein seltsames HTML-Artefakt ist oder ob es damit zu tun hat, wie Python die Zeichenfolge von meinem requestObjekt aufnimmt .
Pat Jones

11
  • "\ r" => Zurück
  • "\ n" => Newline oder Linefeed (Semantik)

  • Unix-basierte Systeme verwenden nur ein "\ n", um eine Textzeile zu beenden.

  • Dos verwendet "\ r \ n", um eine Textzeile zu beenden.
  • Einige andere Maschinen verwendeten nur ein "\ r". (Commodore, Apple II, Mac OS vor OS X usw.)

5

\r wird verwendet, um auf den Zeilenanfang zu zeigen und kann den Text von dort ersetzen, z

main()
{
printf("\nab");
printf("\bsi");
printf("\rha");
}

Erzeugt diese Ausgabe:

hai

\n ist für neue Linie.


4

Kurz gesagt, \ r hat den ASCII-Wert 13 (CR) und \ n hat den ASCII-Wert 10 (LF). Mac verwendet CR als Zeilenbegrenzer (zumindest war ich mir bei modernen Macs nicht sicher), * nix verwendet LF und Windows verwendet beide (CRLF).


1
Mac OS X-Systeme verwenden standardmäßig LF (da es auf BSD Unix basiert).
Dreamlax

3

Zusätzlich zu @ Jon Skeets Antwort:

Traditionell hat Windows \ r \ n, Unix \ n und Mac \ r verwendet, neuere Macs verwenden jedoch \ n, da sie auf Unix basieren.


2

In C # habe ich festgestellt, dass sie \ r \ n in einer Zeichenfolge verwenden.


2

\ r ist Wagenrücklauf; \ n ist Neue Leitung (Zeilenvorschub) ... hängt vom Betriebssystem ab, was jede bedeutet. In diesem Artikel erfahren Sie mehr über den Unterschied zwischen '\ n' und '\ r \ n' ... in C.


1

\ r für Wagenrücklauf verwendet. (ASCII-Wert ist 13) \ n wird für neue Zeile verwendet. (ASCII-Wert ist 10)

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.