Qual è la differenza tra \ r e \ n?


245

Come sono \re \ndiversi? Penso che abbia qualcosa a che fare con Unix vs Windows vs Mac, ma non sono sicuro di come siano diversi e quali cercare / abbinare nelle regex.


1
Questo richiede un tag di lingua. Lingue diverse hanno interpretazioni diverse di '\n'.
Adrian McCarthy,

Risposte:


383

Sono personaggi diversi. \rè il ritorno a capo ed \nè avanzamento riga.

Sulle "vecchie" stampanti, \rrestituiva la testina di stampa all'inizio della riga e \nfaceva avanzare la carta di una riga. Entrambi erano quindi necessari per iniziare a stampare sulla riga successiva.

Ovviamente ora è un po 'irrilevante, anche se a seconda della console potresti essere ancora in grado di utilizzare \rper spostarti all'inizio della riga e sovrascrivere il testo esistente.

Ancora più importante, Unix tende a utilizzare \ncome separatore di linea; Di Windows tende ad usare \r\ncome separatore di linea e Mac (fino a OS 9) utilizzato da utilizzare \rcome separatore di linea. (Mac OS X è Unix-y, quindi utilizza \ninvece; tuttavia potrebbero esserci alcune situazioni di compatibilità in cui \rviene utilizzato.)

Per ulteriori informazioni, consultare l' articolo di Newline di Wikipedia .

EDIT: questo è sensibile al linguaggio. In C # e Java, ad esempio, significa \n sempre Unicode U + 000A, definito come avanzamento riga. In C e C ++ l'acqua è un po 'più fangosa, poiché il significato è specifico della piattaforma. Vedi i commenti per i dettagli.


22
+1 per gli anziani. Uscita terminale utilizzata per controllare direttamente un terminale elettronico glorificato (il tuo TTY prima di quei fantasiosi display CRT). Quindi, otteniamo meravigliosi artefatti di quelli nel ritorno della carrozza e dei personaggi newline (entrambi potrebbero essere necessari, come menzionato da Jon Skeet) e cose come \ a "bell", \ b "backspace" (da non confondere con "delete ") e tutti gli altri personaggi di controllo necessari per comunicare con un tty.
Erjiang,

35
Un altro +1 per gli anziani. Puoi ancora premere Ctrl + G al prompt dei comandi di Windows, premere invio e l'altoparlante del PC emetterà un segnale acustico. È rimasto dai tempi antichi.
Dave Carlile,

@Crappy Coding Guy davvero? Su Vista, dice semplicemente "'' non è riconosciuto come comando interno o esterno"
Ponkadoodle,

2
@AdrianMcCarthy: Naturalmente la domanda non specifica qui C o C ++. In C #, ad esempio, \n è garantito che sia newline (sezione 2.4.4.4). Certo, sarebbe bello se l'OP avesse specificato la piattaforma ... Inoltre, penso che questo livello di dettaglio sarebbe più confuso che utile per qualcuno che sta solo chiedendo la differenza.
Jon Skeet

2
@AdrianMcCarthy: Ma almeno in C # e Java, è un avanzamento riga. È U + 000A, che è nominato da Unicode come "LINE FEED" (e NUOVA LINEA). Modificherò per menzionare il caso speciale di C e C ++, ma credo davvero che siano casi speciali, non viceversa.
Jon Skeet,

91

In C e C ++, \nè un concetto, \rè un carattere ed \r\nè (quasi sempre) un bug di portabilità.

Pensa a un vecchio teletipo. La testina di stampa è posizionata su una linea e su una colonna. Quando si invia un carattere stampabile al tipo di telefono, questo viene stampato nella posizione corrente e si sposta la testa nella colonna successiva. (Concettualmente è lo stesso di una macchina da scrivere, tranne per il fatto che le macchine da scrivere tipicamente spostano la carta rispetto alla testina di stampa.)

Quando volevi finire la riga corrente e iniziare con la riga successiva, dovevi fare due passi separati:

  1. spostare quindi la testina di stampa all'inizio della riga, quindi
  2. spostalo verso il basso alla riga successiva.

ASCII codifica queste azioni come due caratteri di controllo distinti:

  • \x0D(CR) sposta la testina di stampa all'inizio della riga. (Unicode lo codifica come U+000D CARRIAGE RETURN.)
  • \x0A(LF) sposta la testina di stampa verso il basso sulla riga successiva. (Unicode lo codifica come U+000A LINE FEED.)

Ai tempi dei teletipi e delle prime stampanti a tecnologia avanzata, le persone hanno effettivamente sfruttato il fatto che si trattava di due operazioni separate. Inviando un CR senza seguirlo da un LF, è possibile stampare sulla riga già stampata. Ciò ha consentito effetti come accenti, grassetto e sottolineatura. Alcuni sistemi sono stati sovrastampati più volte per impedire che le password siano visibili nella copia cartacea. Sui primi terminali CRT seriali, CR era uno dei modi per controllare la posizione del cursore per aggiornare il testo già sullo schermo.

Ma la maggior parte delle volte, in realtà volevi solo passare alla riga successiva. Invece di richiedere la coppia di caratteri di controllo, alcuni sistemi consentivano solo l'uno o l'altro. Per esempio:

  • Le varianti Unix (incluse le versioni moderne di Mac) usano solo un carattere LF per indicare una nuova riga.
  • I vecchi file Macintosh (pre-OSX) utilizzavano solo un carattere CR per indicare una nuova riga.
  • VMS, CP / M, DOS, Windows e molti protocolli di rete prevedono ancora entrambi: CR LF.
  • Vecchi sistemi IBM che utilizzavano EBCDIC standardizzato su NL - un carattere che non esiste nemmeno nel set di caratteri ASCII. In Unicode, NL è U+0085 NEXT LINE, ma il valore EBCDIC effettivo è 0x15.

Perché sistemi diversi hanno scelto metodi diversi? Semplicemente perché non esisteva uno standard universale. Laddove la tua tastiera probabilmente dice "Invio", le tastiere più vecchie dicevano "Ritorno", che era l'abbreviazione di Ritorno a capo. In effetti, su un terminale seriale, premendo Return si invia effettivamente il carattere CR. Se stavi scrivendo un editor di testo, sarebbe allettante usare quel personaggio appena arrivato dal terminale. Forse è per questo che i vecchi Mac usavano solo CR.

Ora che abbiamo standard , ci sono più modi per rappresentare le interruzioni di riga. Sebbene estremamente raro in natura, Unicode ha nuovi personaggi come:

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

Ancor prima che arrivasse Unicode, i programmatori volevano modi semplici per rappresentare alcuni dei codici di controllo più utili senza preoccuparsi del set di caratteri sottostante. C ha diverse sequenze di escape per rappresentare i codici di controllo:

  • \a (per avviso) che suona la campana del teletipo o che emette un segnale acustico
  • \f (per il feed del modulo) che si sposta all'inizio della pagina successiva
  • \t (per la linguetta) che sposta la testina di stampa nella posizione della linguetta orizzontale successiva

(Questo elenco è intenzionalmente incompleto.)

Questa mappatura avviene in fase di compilazione: il compilatore vede \ae mette qualsiasi valore magico usato per suonare la campana.

Si noti che la maggior parte di questi mnemonici ha correlazioni dirette con i codici di controllo ASCII. Ad esempio, \asarebbe mappare a 0x07 BEL. Un compilatore potrebbe essere scritto per un sistema che utilizzava qualcosa di diverso da ASCII per il set di caratteri host (ad esempio, EBCDIC). La maggior parte dei codici di controllo che avevano mnemonici specifici potevano essere mappati ai codici di controllo in altri set di caratteri.

Huzzah! Portabilità!

Be 'quasi. In C, potrei scrivere printf("\aHello, World!");che suona la campana (o bip) e genera un messaggio. Ma se volessi stampare qualcosa sulla riga successiva, avrei comunque bisogno di sapere cosa richiede la piattaforma host per passare alla riga successiva di output. CR LF? CR? LF? NL? Qualcos'altro? Questo per quanto riguarda la portabilità.

C ha due modalità per l'I / O: binario e testo. In modalità binaria, tutti i dati inviati vengono trasmessi così come sono. Ma in modalità testo, c'è una traduzione di runtime che converte un carattere speciale in qualsiasi cosa la piattaforma host abbia bisogno per una nuova linea (e viceversa).

Fantastico, quindi qual è il personaggio speciale?

Beh, questo è a carico di attuazione, anche, ma c'è un modo implementazione indipendente per specificare che: \n. In genere viene chiamato "carattere di nuova riga".

Questo è un punto sottile ma importante: \n viene mappato in fase di compilazione su un valore di carattere definito dall'implementazione che (in modalità testo) viene quindi mappato nuovamente in fase di esecuzione sul carattere reale (o sequenza di caratteri) richiesto dalla piattaforma sottostante per spostarsi alla riga successiva.

\nè diverso da tutti gli altri letterali di barra rovesciata perché sono coinvolti due mapping. Questa mappatura in due passaggi rende \nsignificativamente diversa da pari \r, che è semplicemente una mappatura in fase di compilazione su CR (o il codice di controllo più simile in qualunque sia il set di caratteri sottostante).

Questo fa scattare molti programmatori C e C ++. Se dovessi effettuare il polling di 100, almeno 99 ti diranno che \nsignifica feed di linea. Questo non è del tutto vero. La maggior parte (forse tutte) le implementazioni C e C ++ usano LF come valore magico intermedio per \n, ma questo è un dettaglio di implementazione. È possibile per un compilatore utilizzare un valore diverso. Infatti, se il set di caratteri host non è un superset di ASCII (ad esempio, se è EBCDIC), \nquasi sicuramente non sarà LF.

Quindi, in C e C ++:

  • \r è letteralmente un ritorno a capo.
  • \nè un valore magico che viene tradotto (in modalità testo) in fase di esecuzione da / verso la semantica della nuova riga della piattaforma host.
  • \r\nè quasi sempre un bug di portabilità. In modalità testo, questo viene tradotto in CR seguito dalla sequenza di nuova riga della piattaforma - probabilmente non è ciò che si intende. In modalità binaria, questo viene tradotto in CR seguito da un valore magico che potrebbe non essere LF - probabilmente non quello che si intende.
  • \x0Aè il modo più portatile per indicare un LF ASCII, ma si desidera farlo solo in modalità binaria. La maggior parte delle implementazioni in modalità testuale lo tratteranno in questo modo \n.

Mi sono imbattuto in questo post mentre cercavo di capire come dividere l'input <textarea> in Python, ed \r\nè in realtà l'unico modo per dividere correttamente le linee in elementi di elenco separati. Mi chiedo se si tratti di uno strano artefatto HTML o se abbia a che fare con il modo in cui Python ingerisce la stringa dal mio requestoggetto.
Pat Jones,

11
  • "\ r" => Ritorna
  • "\ n" => Newline o Linefeed (semantica)

  • I sistemi basati su Unix usano solo una "\ n" per terminare una riga di testo.

  • Dos usa "\ r \ n" per terminare una riga di testo.
  • Alcune altre macchine hanno usato solo un "\ r". (Commodore, Apple II, Mac OS prima di OS X, ecc.)

5

\r viene utilizzato per indicare l'inizio di una riga e può sostituire il testo da lì, ad es

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

Produce questo output:

hai

\n è per la nuova linea.


4

In breve, \ r ha il valore ASCII 13 (CR) e \ n ha il valore ASCII 10 (LF). Mac usa CR come delimitatore di linea (almeno, prima, non sono sicuro per i mac moderni), * nix usa LF e Windows usa entrambi (CRLF).


1
I sistemi Mac OS X utilizzano LF per impostazione predefinita (poiché si basa su BSD Unix).
dreamlax,

3

Oltre alla risposta di @Jon Skeet:

Tradizionalmente Windows utilizzava \ r \ n, Unix \ n e Mac \ r, tuttavia i Mac più recenti usano \ n in quanto basati su unix.


2

in C # ho scoperto che usano \ r \ n in una stringa.


2

è il ritorno a capo; \ n è Nuova riga (avanzamento riga) ... dipende dal sistema operativo per quanto riguarda ciascuno di essi. Leggi questo articolo per ulteriori informazioni sulla differenza tra '\ n' e '\ r \ n' ... in C.


1

utilizzato per il ritorno a capo. (Il valore ASCII è 13) \ n utilizzato per la nuova riga. (Il valore ASCII è 10)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.