В чем разница между \ r и \ n?

245

Чем \rи чем \nотличаются? Я думаю, что это как-то связано с Unix против Windows и Mac, но я не уверен точно, чем они отличаются и что искать / сопоставлять в регулярных выражениях.

Сэм Ли
источник
1
Для этого нужен языковой тег. Разные языки имеют разные интерпретации '\n'.
Адриан Маккарти

Ответы:

383

Они разные персонажи. \rвозврат каретки, и\n перевод строки.

На «старых» принтерах \rотправил печатающую головку обратно в начало строки и\n продвинул бумагу на одну строку. Поэтому оба были необходимы, чтобы начать печать на следующей строке.

Очевидно, что сейчас это не имеет значения, хотя в зависимости от консоли вы все еще сможете использовать \r для перехода к началу строки и перезаписи существующего текста.

Что еще более важно, Unix имеет тенденцию использовать \nв качестве разделителя строк; Windows имеет тенденцию использовать \r\nв качестве разделителя строк, а Mac (до OS 9) используется в \rкачестве разделителя строк. (Mac OS X - Unix-y, поэтому используется \nвместо этого; могут быть некоторые ситуации совместимости, когда\r вместо этого используется.)

Для получения дополнительной информации см. Статью Wikipedia newline .

РЕДАКТИРОВАТЬ: Это зависит от языка. Например, в C # и Java \n всегда означает Unicode U + 000A, который определяется как перевод строки. В C и C ++ вода несколько мутнее, поскольку значение зависит от платформы. Смотрите комментарии для деталей.

Джон Скит
источник
22
+1 для пожилых людей. Выход терминала используется для непосредственного управления прославленным электронным терминалом (ваш TTY до того, как на экране появятся эти модные ЭЛТ). Следовательно, мы получаем замечательные артефакты тех, кто находится в символах возврата каретки и перевода строки (оба из которых могут понадобиться, как упоминал Джон Скит), и такие вещи, как \ a "bell", \ b "backspace" (не путать с "delete" ") и все остальные управляющие символы, необходимые для связи с tty.
erjiang
35
Еще +1 для пожилых людей. Вы все еще можете нажать Ctrl + G в командной строке Windows, нажать Enter, и динамик ПК подаст звуковой сигнал. Это осталось с древних времен.
Дэйв Карлайл
@ Крэппи, Парень Кодирования действительно? В Vista просто говорится, что «не распознается как внутренняя или внешняя команда»
Ponkadoodle,
2
@AdrianMcCarthy: Конечно, вопрос здесь не указывает C или C ++. В C #, например , \n является гарантированно новой строки (раздел 2.4.4.4). Конечно, было бы неплохо, если бы ОП указала платформу ... Кроме того, я думаю, что этот уровень детализации был бы более запутанным, чем полезным для тех, кто просто спрашивает разницу.
Джон Скит
2
@AdrianMcCarthy: Но в C # и Java , по крайней мере, она является линия подачи. Это U + 000A, который Unicode назвал «LINE FEED» (и NEW LINE). Я отредактирую, чтобы упомянуть особый случай C и C ++, но я действительно верю, что это особые случаи, а не наоборот.
Джон Скит
91

В C и C ++ \nэто понятие, \rсимвол и \r\n(почти всегда) ошибка переносимости.

Подумайте о старом телетайпе. Печатающая головка расположена на некоторой строке и в некотором столбце. Когда вы отправляете печатный символ в телетайп, он печатает символ в текущей позиции и перемещает голову к следующему столбцу. (Концептуально это то же самое, что пишущая машинка, за исключением того, что пишущие машинки обычно перемещают бумагу относительно печатающей головки.)

Если вы хотите закончить текущую строку и начать со следующей строки, вам нужно сделать два отдельных шага:

  1. переместите печатающую головку обратно в начало строки, затем
  2. переместить его на следующую строку.

ASCII кодирует эти действия в виде двух разных управляющих символов:

  • \x0D(CR) перемещает печатающую головку обратно в начало строки. (Юникод кодирует это как U+000D CARRIAGE RETURN.)
  • \x0A(LF) перемещает печатающую головку вниз на следующую строку. (Юникод кодирует это как U+000A LINE FEED.)

Во времена телетайпов и ранних технологических принтеров люди фактически использовали тот факт, что это были две отдельные операции. Отправив CR, не следуя за ним через LF, вы можете печатать поверх уже напечатанной строки. Это позволило такие эффекты, как акценты, жирный шрифт и подчеркивание. Некоторые системы несколько раз печатали, чтобы пароли не были видны в печатном виде. На ранних последовательных терминалах CRT CR был одним из способов управления положением курсора для обновления текста, уже находящегося на экране.

Но в большинстве случаев вы просто хотели перейти на следующую строку. Вместо того, чтобы требовать пару управляющих символов, некоторые системы допускают только один или другой. Например:

  • Варианты Unix (включая современные версии Mac) используют только символ LF для обозначения новой строки.
  • Старые (до OSX) файлы Macintosh использовали только символ CR для обозначения новой строки.
  • VMS, CP / M, DOS, Windows и многие сетевые протоколы по- прежнему ожидают и того, и другого: CR LF.
  • Старые системы IBM, которые использовали EBCDIC, стандартизированный по NL - символ, которого даже нет в наборе символов ASCII. В Unicode NL есть U+0085 NEXT LINE, но фактическое значение EBCDIC равно 0x15.

Почему разные системы выбрали разные методы? Просто потому, что не было универсального стандарта. Там, где ваша клавиатура, вероятно, говорит «Enter», на старых клавиатурах говорилось «Return», что было коротким для возврата каретки. Фактически, на последовательном терминале нажатие Return фактически отправляет символ CR. Если бы вы писали текстовый редактор, было бы заманчиво использовать этот символ так, как он поступил из терминала. Возможно, поэтому старые Mac использовали только CR.

Теперь, когда у нас есть стандарты , есть больше способов представить разрывы строк. Несмотря на то, что Unicode чрезвычайно редок в дикой природе, в нем есть новые символы, такие как

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

Еще до появления Unicode программисты хотели простые способы представления некоторых наиболее полезных управляющих кодов, не беспокоясь о базовом наборе символов. C имеет несколько escape-последовательностей для представления управляющих кодов:

  • \a (для предупреждения), который звонит в телетайп или звонит терминалу
  • \f (для подачи формы), который перемещается в начало следующей страницы
  • \t (для вкладки), которая перемещает печатающую головку в следующую горизонтальную позицию вкладки

(Этот список намеренно неполон.)

Это отображение происходит во время компиляции - компилятор видит \aи помещает любое магическое значение, используемое для звонка.

Обратите внимание, что большинство этих мнемоник имеют прямые корреляции с управляющими кодами ASCII. Например, \aбудет отображаться в 0x07 BEL. Компилятор может быть написан для системы, которая использует что-то отличное от ASCII для набора символов хоста (например, EBCDIC). Большинство контрольных кодов, которые имели определенную мнемонику, могут быть сопоставлены с контрольными кодами в других наборах символов.

Ура! Переносимость!

Ну, почти. В C я мог бы написать, printf("\aHello, World!");который звонит в колокол (или подает звуковой сигнал) и выводит сообщение. Но если бы я захотел напечатать что-то на следующей строке, мне все равно нужно было бы знать, что требуется платформе хоста для перехода к следующей строке вывода. CR LF? CR? LF? NL? Что-то другое? Так много для мобильности.

C имеет два режима ввода / вывода: двоичный и текстовый. В двоичном режиме все отправленные данные передаются как есть. Но в текстовом режиме есть перевод во время выполнения, который преобразует специальный символ в то, что требуется платформе хоста для новой строки (и наоборот).

Отлично, так в чем же особенность?

Ну, это зависит от реализации, тоже, но есть способ реализации , независим , чтобы указать его: \n. Обычно это называется «символ новой строки».

Это тонкий, но важный момент: \n сопоставляется во время компиляции с определенным для реализации значением символа, которое (в текстовом режиме) затем снова отображается во время выполнения на фактический символ (или последовательность символов), требуемый базовой платформой для перемещения на следующую строку.

\nотличается от всех других литералов обратной косой черты, потому что здесь задействованы два отображения. Это двухэтапное отображение \nзначительно отличается от четного \r, которое представляет собой просто отображение во время компиляции в CR (или наиболее похожий управляющий код в любом базовом наборе символов).

Это сбивает с толку многих программистов на C и C ++. Если бы вы опросили 100 из них, по крайней мере 99 скажет вам, что \nозначает перевод строки. Это не совсем правда. Большинство (возможно, все) реализаций C и C ++ используют LF в качестве магического промежуточного значения для \n, но это деталь реализации. Для компилятора возможно использовать другое значение. Фактически, если набор символов хоста не является расширенным набором ASCII (например, если это EBCDIC), то \nпочти наверняка не будет LF.

Итак, в C и C ++:

  • \r буквально возврат каретки.
  • \nявляется магическим значением, которое переводится (в текстовом режиме) во время выполнения в / из семантики новой строки платформы хоста.
  • \r\nпочти всегда ошибка переносимости. В текстовом режиме это переводится в CR, за которым следует последовательность новой строки платформы - вероятно, не то, что предполагалось. В двоичном режиме это переводится в CR, за которым следует некоторое магическое значение, которое может не быть LF - возможно, не тем, что предполагалось.
  • \x0Aявляется наиболее переносимым способом обозначения ASCII LF, но вы хотите делать это только в двоичном режиме. Большинство реализаций в текстовом режиме будут воспринимать это как \n.
Адриан Маккарти
источник
Наткнулся на этот пост, пытаясь понять, как разделить ввод <textarea> в Python, и \r\nна самом деле это единственный способ, которым я мог бы правильно разделить строки на отдельные элементы списка. Это заставляет меня задаться вопросом, является ли это каким-то странным артефактом HTML, или это связано со способом, которым Python получает строку из моего requestобъекта.
Пэт Джонс
11
  • "\ r" => Возврат
  • "\ n" => Новая строка или перевод строки (семантика)

  • Системы на основе Unix используют просто «\ n» для окончания строки текста.

  • Dos использует «\ r \ n» для окончания строки текста.
  • Некоторые другие машины использовали просто "\ r". (Commodore, Apple II, Mac OS до OS X и т. Д.)
NoMoreZealots
источник
5

\r используется для указания на начало строки и может заменить текст оттуда, например

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

Производит этот вывод:

hai

\n для новой линии.

ДАЯ ФИЛИП
источник
4

Короче говоря, \ r имеет значение ASCII 13 (CR), а \ n имеет значение ASCII 10 (LF). Mac использует CR в качестве разделителя строк (по крайней мере, раньше, я не уверен для современных macs), * nix использует LF, а Windows использует оба (CRLF).

Иосип Медведь
источник
1
Системы Mac OS X используют LF по умолчанию (поскольку он основан на BSD Unix).
сонлакс
3

В дополнение к ответу @Jon Skeet:

Традиционно Windows использует \ r \ n, Unix \ n и Mac \ r, однако более новые Mac используют \ n, поскольку они основаны на Unix.

Greg
источник
2

в C # я обнаружил, что они используют \ r \ n в строке.

Wesley
источник
2

\ r - возврат каретки; \ n - это новая строка (перевод строки) ... зависит от того, что означает каждая из ОС. Прочтите эту статью, чтобы узнать больше о разнице между '\ n' и '\ r \ n' ... в C.

Натан Лодинг
источник
1

используется для возврата каретки. (Значение ASCII равно 13) \ n используется для новой строки. (Значение ASCII равно 10)

Манжит Кумар
источник