¿Cuál es la diferencia entre \ r y \ n?

245

¿Cómo son \ry \ndiferentes? Creo que tiene algo que ver con Unix vs. Windows vs. Mac, pero no estoy seguro de cómo son exactamente diferentes, y cuál buscar / emparejar en expresiones regulares.

Sam Lee
fuente
1
Esto necesita una etiqueta de idioma. Diferentes idiomas tienen diferentes interpretaciones de '\n'.
Adrian McCarthy

Respuestas:

383

Son personajes diferentes. \res el retorno de carro y \nes el avance de línea.

En impresoras "viejas", \renvió el cabezal de impresión de regreso al inicio de la línea y \navanzó el papel una línea. Por lo tanto, ambos fueron necesarios para comenzar a imprimir en la siguiente línea.

Obviamente, eso es algo irrelevante ahora, aunque dependiendo de la consola aún puede usar \rpara moverse al inicio de la línea y sobrescribir el texto existente.

Más importante aún, Unix tiende a usarse \ncomo un separador de línea; Windows tiende a usarse \r\ncomo separador de línea y Macs (hasta OS 9) solía usarse \rcomo separador de línea. (Mac OS X es Unix-y, por lo tanto, usa en su \nlugar; sin embargo, puede haber algunas situaciones de compatibilidad en las que \rse usa).

Para obtener más información, consulte el artículo de la nueva línea de Wikipedia .

EDITAR: Esto es sensible al lenguaje. En C # y Java, por ejemplo, \n siempre significa Unicode U + 000A, que se define como avance de línea. En C y C ++, el agua es algo más turbia, ya que el significado es específico de la plataforma. Ver comentarios para más detalles.

Jon Skeet
fuente
22
+1 para personas mayores. La salida del terminal se usa para controlar directamente un terminal electrónico glorificado (su TTY antes de las elegantes pantallas CRT). Por lo tanto, obtenemos artefactos maravillosos de aquellos en el retorno de carro y caracteres de nueva línea (los cuales podrían ser necesarios, como mencionó Jon Skeet) y cosas como \ a "campana", \ b "retroceso" (no confundir con "eliminar" "), y todos los demás caracteres de control necesarios para comunicarse con un tty.
erjiang
35
Otro +1 para personas mayores. Todavía puede presionar Ctrl + G en el símbolo del sistema de Windows, presionar enter y el altavoz de la PC emitirá un pitido. Eso queda de la antigüedad.
Dave Carlile el
@Crappy Coding Guy realmente? En Vista, solo dice "" no se reconoce como un comando interno o externo "
Ponkadoodle
2
@AdrianMcCarthy: Por supuesto, la pregunta en realidad no especifica C o C ++ aquí. En C #, por ejemplo, \n se garantiza que sea nueva línea (sección 2.4.4.4). Por supuesto, sería bueno si el OP hubiera especificado la plataforma ... Además, creo que este nivel de detalle sería más confuso que útil para alguien que solo pregunta la diferencia.
Jon Skeet
2
@AdrianMcCarthy: Pero en C # y Java al menos, es un avance de línea. Es U + 000A, que Unicode denomina "ALIMENTACIÓN DE LÍNEA" (y NUEVA LÍNEA). Voy a editar para mencionar el caso especial de C y C ++, pero realmente creo que esos son casos especiales, no al revés.
Jon Skeet
91

En C y C ++, \nes un concepto, \res un personaje y \r\nes (casi siempre) un error de portabilidad.

Piensa en un viejo teletipo. El cabezal de impresión se coloca en una línea y en una columna. Cuando envía un carácter imprimible al teletipo, imprime el carácter en la posición actual y mueve la cabeza a la siguiente columna. (Esto es conceptualmente lo mismo que una máquina de escribir, excepto que las máquinas de escribir generalmente mueven el papel con respecto al cabezal de impresión).

Cuando quería terminar la línea actual y comenzar en la siguiente línea, tenía que hacer dos pasos separados:

  1. mueva el cabezal de impresión de nuevo al comienzo de la línea, luego
  2. muévelo hacia la siguiente línea.

ASCII codifica estas acciones como dos caracteres de control distintos:

  • \x0D(CR) mueve el cabezal de impresión de regreso al comienzo de la línea. (Unicode codifica esto como U+000D CARRIAGE RETURN.)
  • \x0A(LF) mueve el cabezal de impresión hacia abajo a la siguiente línea. (Unicode codifica esto como U+000A LINE FEED.)

En los días de los teletipos y las primeras impresoras tecnológicas, las personas realmente aprovecharon el hecho de que se trataba de dos operaciones separadas. Al enviar un CR sin seguirlo por un LF, puede imprimir sobre la línea que ya imprimió. Esto permitió efectos como acentos, negrita y subrayado. Algunos sistemas se sobreimprimen varias veces para evitar que las contraseñas sean visibles en la copia impresa. En los primeros terminales seriales de CRT, CR era una de las formas de controlar la posición del cursor para actualizar el texto que ya estaba en la pantalla.

Pero la mayoría de las veces, en realidad solo quería pasar a la siguiente línea. En lugar de requerir el par de caracteres de control, algunos sistemas permitieron solo uno u otro. Por ejemplo:

  • Las variantes de Unix (incluidas las versiones modernas de Mac) utilizan solo un carácter LF para indicar una nueva línea.
  • Los archivos Macintosh antiguos (anteriores a OSX) usaban solo un carácter CR para indicar una nueva línea.
  • VMS, CP / M, DOS, Windows y muchos protocolos de red todavía esperan ambos: CR LF.
  • Sistemas IBM antiguos que usaban EBCDIC estandarizado en NL, un carácter que ni siquiera existe en el conjunto de caracteres ASCII. En Unicode, NL es U+0085 NEXT LINE, pero el valor real EBCDIC es 0x15.

¿Por qué diferentes sistemas eligieron diferentes métodos? Simplemente porque no había un estándar universal. Cuando su teclado probablemente dice "Enter", los teclados más antiguos solían decir "Return", que era la abreviatura de Carriage Return. De hecho, en un terminal en serie, al presionar Retorno en realidad se envía el carácter CR. Si estuviera escribiendo un editor de texto, sería tentador usar ese carácter tal como vino desde el terminal. Quizás es por eso que los Macs más antiguos usaban solo CR.

Ahora que tenemos estándares , hay más formas de representar saltos de línea. Aunque extremadamente raro en la naturaleza, Unicode tiene nuevos personajes como:

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

Incluso antes de que apareciera Unicode, los programadores querían formas simples de representar algunos de los códigos de control más útiles sin preocuparse por el conjunto de caracteres subyacente. C tiene varias secuencias de escape para representar códigos de control:

  • \a (para alerta) que suena el timbre del teletipo o hace sonar el terminal
  • \f (para el formulario de alimentación) que se mueve al comienzo de la página siguiente
  • \t (para pestaña) que mueve el cabezal de impresión a la siguiente posición de pestaña horizontal

(Esta lista está intencionalmente incompleta).

Este mapeo ocurre en tiempo de compilación: el compilador ve \ay pone cualquier valor mágico que se use para tocar el timbre.

Tenga en cuenta que la mayoría de estos mnemónicos tienen correlaciones directas con los códigos de control ASCII. Por ejemplo, \ase asignaría a 0x07 BEL. Se podría escribir un compilador para un sistema que utilizara algo distinto de ASCII para el conjunto de caracteres del host (por ejemplo, EBCDIC). La mayoría de los códigos de control que tenían mnemónicos específicos podrían asignarse a códigos de control en otros conjuntos de caracteres.

Huzzah! ¡Portabilidad!

Bueno, casi. En C, podría escribir printf("\aHello, World!");qué suena la campana (o suena) y emite un mensaje. Pero si quisiera imprimir algo en la siguiente línea, aún necesitaría saber qué requiere la plataforma host para pasar a la siguiente línea de salida. CR LF? CR? LF? NL? ¿Algo más? Demasiado para la portabilidad.

C tiene dos modos para E / S: binario y texto. En modo binario, los datos que se envían se transmiten tal cual. Pero en modo texto, hay una traducción en tiempo de ejecución que convierte un carácter especial a lo que la plataforma de host necesita para una nueva línea (y viceversa).

Genial, ¿cuál es el personaje especial?

Bueno, eso depende de la aplicación, también, pero hay una manera independiente de la implementación para especificar que: \n. Normalmente se llama el "personaje de nueva línea".

Este es un punto sutil pero importante: \n se asigna en tiempo de compilación a un valor de carácter definido por la implementación que (en modo texto) se vuelve a asignar en tiempo de ejecución al carácter real (o secuencia de caracteres) requerido por la plataforma subyacente para moverse a la siguiente línea

\nes diferente de todos los demás literales de barra diagonal inversa porque hay dos asignaciones involucradas. Este mapeo de dos pasos hace \nsignificativamente diferente que incluso \r, que es simplemente un mapeo en tiempo de compilación a CR (o el código de control más similar en cualquier conjunto de caracteres subyacente).

Esto dispara muchos programadores C y C ++. Si tuviera que sondear 100 de ellos, al menos 99 le indicarán que eso \nsignifica avance de línea. Esto no es enteramente verdad. La mayoría (quizás todas) las implementaciones de C y C ++ usan LF como el valor intermedio mágico para \n, pero ese es un detalle de implementación. Es factible que un compilador use un valor diferente. De hecho, si el conjunto de caracteres del host no es un superconjunto de ASCII (p. Ej., Si es EBCDIC), \nes casi seguro que no será LF.

Entonces, en C y C ++:

  • \r es literalmente un retorno de carro.
  • \nes un valor mágico que se traduce (en modo de texto) en tiempo de ejecución a / desde la semántica de nueva línea de la plataforma host.
  • \r\nCasi siempre es un error de portabilidad. En modo de texto, esto se traduce a CR seguido de la secuencia de nueva línea de la plataforma, probablemente no lo que se pretende. En modo binario, esto se traduce a CR seguido de algún valor mágico que podría no ser LF, posiblemente no lo que se pretende.
  • \x0Aes la forma más portátil de indicar un ASCII LF, pero solo desea hacerlo en modo binario. La mayoría de las implementaciones en modo texto tratarán eso como \n.
Adrian McCarthy
fuente
Encontré esta publicación mientras intentaba descubrir cómo dividir la entrada <textarea> en Python, y en \r\nrealidad es la única forma en que podría dividir correctamente las líneas en elementos de lista separados. Me hace preguntarme si esto es un artefacto HTML extraño, o si tiene que ver con la forma en que Python ingiere la cadena de mi requestobjeto.
Pat Jones
11
  • "\ r" => Volver
  • "\ n" => Newline o Linefeed (semántica)

  • Los sistemas basados ​​en Unix usan solo un "\ n" para finalizar una línea de texto.

  • Dos usa "\ r \ n" para finalizar una línea de texto.
  • Algunas otras máquinas utilizan solo un "\ r". (Commodore, Apple II, Mac OS antes de OS X, etc.)
NoMoreZealots
fuente
5

\r se usa para señalar el inicio de una línea y puede reemplazar el texto desde allí, p. ej.

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

Produce esta salida:

hai

\n Es para nueva línea.

DAYA PHILIP
fuente
4

En resumen, \ r tiene un valor ASCII 13 (CR) y \ n tiene un valor ASCII 10 (LF). Mac usa CR como delimitador de línea (al menos, lo hizo antes, no estoy seguro para los Mac modernos), * nix usa LF y Windows usa ambos (CRLF).

Josip Medved
fuente
1
Los sistemas Mac OS X usan LF por defecto (ya que está basado en BSD Unix).
dreamlax
3

Además de la respuesta de @Jon Skeet:

Tradicionalmente, Windows ha usado \ r \ n, Unix \ ny Mac \ r, sin embargo, las Mac más nuevas usan \ n ya que están basadas en Unix.

Greg
fuente
2

en C # descubrí que usan \ r \ n en una cadena.

Wesley
fuente
2

\ r es el retorno del carro; \ n es Nueva línea (avance de línea) ... depende del sistema operativo en cuanto a lo que cada uno significa. Lea este artículo para obtener más información sobre la diferencia entre '\ n' y '\ r \ n' ... en C.

Nathan Loding
fuente
1

\ r utilizado para el retorno de carro. (El valor ASCII es 13) \ n usado para una nueva línea. (El valor ASCII es 10)

Manjeet Kumar
fuente