Jaka jest różnica między \ ri \ n?


245

W jaki sposób \ri \ninaczej? Myślę, że ma to coś wspólnego z Unix vs. Windows vs. Mac, ale nie jestem pewien, jak dokładnie się różnią i które szukać / dopasowywać w wyrażeniach regularnych.


1
To wymaga znacznika języka. Różne języki mają różne interpretacje '\n'.
Adrian McCarthy

Odpowiedzi:


383

Są różnymi postaciami. \rjest znakiem powrotu karetki i \njest wierszem.

Na „starych” drukarkach \rwysłał głowicę drukującą z powrotem na początek linii i \nprzesunął papier o jedną linię. Oba były zatem konieczne, aby rozpocząć drukowanie w następnym wierszu.

Oczywiście jest to teraz trochę nieistotne, chociaż w zależności od konsoli nadal możesz być w stanie \rprzejść do początku linii i zastąpić istniejący tekst.

Co ważniejsze, Unix zwykle używa \njako separatora linii; System Windows ma tendencję do wykorzystania \r\njako separator linii i Mac OS (do 9) stosowanego do wykorzystania \rjako separator linii. (Mac OS X to Unix-y, więc używa \nzamiast tego; mogą jednak wystąpić pewne sytuacje kompatybilności \r.)

Aby uzyskać więcej informacji, zobacz artykuł z nowej linii w Wikipedii .

EDYCJA: Jest to zależne od języka. Na przykład w języku C # i Javie \n zawsze oznacza Unicode U + 000A, który jest zdefiniowany jako przesunięcie wiersza. W C i C ++ woda jest nieco bardziej mętna, ponieważ znaczenie jest specyficzne dla platformy. Zobacz komentarze, aby uzyskać szczegółowe informacje.


22
+1 dla osób starszych. Wyjście terminala używane do bezpośredniego sterowania chwalebnym terminalem elektronicznym (twój TTY przed tymi fantazyjnymi wyświetlaczami CRT). W związku z tym otrzymujemy wspaniałe artefakty znaków powrotu karetki i znaków nowej linii (które mogą być potrzebne, jak wspomniał Jon Skeet) i rzeczy takich jak „dzwonek”, „b” backspace (nie mylić z „usuń” ”) i wszystkie inne znaki sterujące potrzebne do komunikacji z tty.
erjiang

35
Kolejny +1 dla osób starszych. Nadal możesz nacisnąć Ctrl + G w wierszu polecenia systemu Windows, nacisnąć Enter, a głośnik komputera wyda sygnał dźwiękowy. To zostało z czasów starożytnych.
Dave Carlile

@Crappy Coding Guy naprawdę? W
systemie Vista napis

2
@AdrianMcCarthy: Oczywiście pytanie nie określa tutaj C ani C ++. C #, na przykład \n jest gwarancją linia (sekcja 2.4.4.4). Oczywiście byłoby miło, gdyby PO określił platformę ... Poza tym uważam, że ten poziom szczegółowości byłby bardziej mylący niż przydatny dla kogoś, kto tylko pyta o różnicę.
Jon Skeet

2
@AdrianMcCarthy: Ale przynajmniej w języku C # i Javie jest to linia. Jest to U + 000A, który Unicode nazywa „LINE FEED” (i NEW LINE). Zredaguję, aby wspomnieć o specjalnym przypadku C i C ++, ale naprawdę wierzę, że są to specjalne przypadki, a nie na odwrót.
Jon Skeet

91

W C i C ++ \nkoncepcja \rjest postacią i \r\n(prawie zawsze) jest błędem przenośności.

Pomyśl o starym telegrafie. Głowica drukująca znajduje się w pewnej linii i kolumnie. Gdy wysyłasz znak do wydrukowania na typ teletekstu, drukuje on znak w bieżącej pozycji i przesuwa głowę do następnej kolumny. (Jest to koncepcyjnie to samo co maszyna do pisania, z tą różnicą, że maszyny do pisania zwykle przesuwały papier w stosunku do głowicy drukującej).

Gdy chciałeś zakończyć bieżącą linię i zacząć od następnej linii, musiałeś zrobić dwa oddzielne kroki:

  1. następnie przesuń głowicę drukującą z powrotem na początek linii
  2. przenieś go w dół do następnej linii.

ASCII koduje te akcje jako dwa różne znaki kontrolne:

  • \x0D(CR) przesuwa głowicę drukującą z powrotem na początek linii. (Unicode koduje to jako U+000D CARRIAGE RETURN.)
  • \x0A(LF) przesuwa głowicę drukującą w dół do następnego wiersza. (Unicode koduje to jako U+000A LINE FEED.)

W czasach drukarek teletypów i wczesnych technologii ludzie korzystali z faktu, że były to dwie osobne operacje. Wysyłając CR bez podążania za nim przez LF, możesz drukować na linii, którą już wydrukowałeś. Pozwoliło to na takie efekty, jak akcenty, pogrubienie i podkreślenie. Niektóre systemy drukowały się kilkakrotnie, aby uniemożliwić wyświetlanie haseł na wydruku. We wczesnych szeregowych terminalach CRT CR był jednym ze sposobów kontrolowania pozycji kursora w celu aktualizacji tekstu już na ekranie.

Ale w większości przypadków po prostu chciałeś przejść do następnej linii. Zamiast wymagać pary znaków kontrolnych, niektóre systemy dopuszczały tylko jeden lub drugi. Na przykład:

  • Warianty uniksowe (w tym nowoczesne wersje komputerów Mac) używają tylko znaku LF, aby wskazać nową linię.
  • Stare (wcześniejsze niż OSX) pliki Macintosh używały tylko znaku CR do oznaczenia nowej linii.
  • VMS, CP / M, DOS, Windows i wiele protokołów sieciowych wciąż oczekują obu: CR LF.
  • Stare systemy IBM, które używały standardu EBCDIC na NL - znak, który nawet nie istnieje w zestawie znaków ASCII. W Unicode NL jest U+0085 NEXT LINE, ale rzeczywista wartość EBCDIC to 0x15.

Dlaczego różne systemy wybierają różne metody? Po prostu dlatego, że nie było uniwersalnego standardu. Tam, gdzie klawiatura prawdopodobnie mówi „Enter”, starsze klawiatury zwykły mówić „Return”, co było skrótem od Carriage Return. W rzeczywistości naciśnięcie klawisza Return na terminalu szeregowym powoduje wysłanie znaku CR. Jeśli piszesz edytor tekstów, kuszące byłoby użycie tego znaku, który pojawił się w terminalu. Być może dlatego starsze komputery Mac używały tylko CR.

Teraz, gdy mamy standardy , istnieje więcej sposobów reprezentowania podziałów linii. Chociaż niezwykle rzadko występuje w środowisku naturalnym, Unicode ma nowe znaki, takie jak:

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

Jeszcze zanim pojawił się Unicode, programiści chcieli prostych sposobów przedstawienia niektórych z najbardziej użytecznych kodów kontrolnych, nie martwiąc się o podstawowy zestaw znaków. C ma kilka sekwencji ucieczki do reprezentowania kodów kontrolnych:

  • \a (dla alertu), który dzwoni dzwonkiem teletypu lub wydaje sygnał dźwiękowy na terminalu
  • \f (dla wysuwu formularza), który przechodzi na początek następnej strony
  • \t (dla zakładki), która przesuwa głowicę drukującą do następnej poziomej pozycji zakładki

(Ta lista jest celowo niekompletna).

To mapowanie odbywa się w czasie kompilacji - kompilator widzi \ai umieszcza dowolną magiczną wartość używaną do dzwonienia.

Zauważ, że większość tych mnemoników ma bezpośrednie korelacje z kodami sterującymi ASCII. Na przykład \aodwzorowałby na 0x07 BEL. Kompilator mógłby zostać napisany dla systemu, który używał czegoś innego niż ASCII dla zestawu znaków hosta (np. EBCDIC). Większość kodów sterujących, które miały określone mnemoniki, można było odwzorować na kody sterujące w innych zestawach znaków.

Huzzah! Ruchliwość!

Cóż prawie. W C mógłbym napisać, printf("\aHello, World!");który dzwoni (lub wydaje sygnał dźwiękowy) i wysyła komunikat. Ale jeśli chciałbym następnie wydrukować coś w następnym wierszu, nadal musiałbym wiedzieć, czego wymaga platforma hosta, aby przejść do następnego wiersza wyników. CR LF? CR? LF? NL? Coś innego? Tyle o przenośności.

C ma dwa tryby wejścia / wyjścia: binarny i tekstowy. W trybie binarnym wszelkie przesyłane dane są przesyłane w stanie, w jakim się znajdują. Ale w trybie tekstowym istnieje tłumaczenie w czasie wykonywania, które konwertuje znak specjalny na wszystko, czego potrzebuje platforma hosta dla nowej linii (i odwrotnie).

Świetnie, więc jaki jest charakter specjalny?

Dobrze, że to realizacja uzależniona, zbyt, ale nie sposób niezależny od implementacji, aby go określić: \n. Zazwyczaj nazywa się to „znakiem nowej linii”.

Jest to subtelny, ale ważny punkt: \n jest odwzorowywany w czasie kompilacji na wartość znaku zdefiniowaną w implementacji, która (w trybie tekstowym) jest następnie odwzorowywana w czasie wykonywania na rzeczywisty znak (lub sekwencję znaków) wymagany przez platformę do poruszania się do następnej linii.

\nróżni się od wszystkich innych literałów odwrotnego ukośnika, ponieważ w grę wchodzą dwa odwzorowania. To dwuetapowe odwzorowanie \nznacznie różni się od nawet \r, które jest po prostu odwzorowaniem w czasie kompilacji na CR (lub najbardziej podobny kod sterujący w jakimkolwiek podstawowym zestawie znaków).

To wywołuje u wielu programistów C i C ++. Jeśli chcesz sondować 100 z nich, co najmniej 99 powie Ci, że \nto oznacza wiersz. To nie do końca prawda. Większość (być może wszystkie) implementacje C i C ++ używają LF jako magicznej wartości pośredniej \n, ale jest to szczegół implementacji. Kompilator może użyć innej wartości. W rzeczywistości, jeśli zestaw znaków hosta nie jest nadzbiorem ASCII (np. Jeśli jest to EBCDIC), to \nprawie na pewno nie będzie LF.

Tak więc w C i C ++:

  • \r to dosłownie powrót karetki.
  • \nto magiczna wartość, która jest tłumaczona (w trybie tekstowym) w czasie wykonywania na semantykę nowej linii platformy hosta.
  • \r\njest prawie zawsze błędem przenośności. W trybie tekstowym jest to tłumaczone na CR, a następnie sekwencja nowej linii platformy - prawdopodobnie nie w zamierzony sposób. W trybie binarnym jest to tłumaczone na CR, po którym następuje pewna magiczna wartość, która może nie być LF - być może nie jest zgodna z przeznaczeniem.
  • \x0Ajest najbardziej przenośnym sposobem na wskazanie ASFII LF, ale chcesz to zrobić tylko w trybie binarnym. Większość implementacji w trybie tekstowym będzie tak traktować \n.

Przeszedłem przez ten post, próbując dowiedzieć się, jak podzielić <textarea> dane wejściowe w Pythonie, i \r\ntak naprawdę jest to jedyny sposób, w jaki mogłem poprawnie podzielić linie na osobne elementy listy. Zastanawiam się, czy to jakiś dziwny artefakt HTML, czy może ma to związek ze sposobem, w jaki Python pobiera ciąg z mojego requestobiektu.
Pat Jones

11
  • „\ r” => Return
  • "\ n" => Newline lub Linefeed (semantyka)

  • Systemy uniksowe używają tylko „\ n” do zakończenia linii tekstu.

  • Dos używa „\ r \ n” do zakończenia linii tekstu.
  • Niektóre inne maszyny używały tylko „\ r”. (Commodore, Apple II, Mac OS przed OS X itp.)

5

\r służy do wskazywania początku linii i może stamtąd zastąpić tekst, np

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

Daje to wyjście:

hai

\n jest dla nowej linii.


4

W skrócie \ r ma wartość ASCII 13 (CR), a \ n ma wartość ASCII 10 (LF). Mac używa CR jako separatora linii (przynajmniej tak było wcześniej, nie jestem pewien co do nowoczesnych Mac), * nix używa LF, a Windows używa obu (CRLF).


1
Systemy Mac OS X domyślnie używają LF (ponieważ opiera się na BSD Unix).
dreamlax

3

Oprócz odpowiedzi @Jona Skeeta:

Tradycyjnie Windows używa \ r \ n, Unix \ n i Mac \ r, jednak nowsze Mac używają \ n, ponieważ są oparte na Uniksie.



2

zwrot karetki; \ n to Nowa linia (wysuw wiersza) ... zależy od systemu operacyjnego, co to oznacza. Przeczytaj ten artykuł, aby uzyskać więcej informacji na temat różnicy między „\ n” a „\ r \ n” ... w C.


1

służy do powrotu karetki. (Wartość ASCII to 13) \ n użyte w nowym wierszu. (Wartość ASCII wynosi 10)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.