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

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


person Sam Lee    schedule 14.08.2009    source источник
comment
Для этого нужен языковой тег. Разные языки имеют разные интерпретации '\n'.   -  person Adrian McCarthy    schedule 16.03.2014


Ответы (9)


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

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

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

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

Для получения дополнительной информации см. статью Википедии о новой строке.

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

person Jon Skeet    schedule 14.08.2009
comment
+1 для стариков. Выход терминала, используемый для прямого управления прославленным электронным терминалом (вашим телетайпом до тех причудливых ЭЛТ-дисплеев). Следовательно, мы получаем замечательные артефакты в символах возврата каретки и новой строки (оба из них могут понадобиться, как упоминал Джон Скит), а также такие вещи, как \a bell, \b backspace (не путать с удалением) и все другие управляющие символы, необходимые для связи с tty. - person erjiang; 14.08.2009
comment
Еще +1 для стариков. Вы по-прежнему можете нажать Ctrl+G в командной строке Windows, нажать Enter, и динамик ПК издаст звуковой сигнал. Это осталось с древних времен. - person Dave Carlile; 14.08.2009
comment
@Crappy Coding Guy правда? В Vista он просто говорит, что «не распознается как внутренняя или внешняя команда». - person Ponkadoodle; 30.05.2010
comment
\n не обязательно является символом перевода строки ASCII. Это соглашение C и C++ для ссылки на разделитель строк хост-платформы при выполнении ввода-вывода в текстовом режиме. В большинстве реализаций используется символ перевода строки ASCII для \n, но я не думаю, что стандарты C или C++ действительно требуют этого. Если вам нужна новая строка, используйте \n. Если вам нужен перевод строки, используйте \x0A. Напротив, \r должен быть возвратом каретки ASCII, независимо от реализации. - person Adrian McCarthy; 02.03.2012
comment
@AdrianMcCarthy: Конечно, вопрос на самом деле не указывает C или C++ здесь. В C#, например, \n является гарантированно новой строкой (раздел 2.4.4.4). Конечно, было бы неплохо, если бы OP указал платформу ... Кроме того, я думаю, что этот уровень детализации был бы скорее запутанным, чем полезным для кого-то, кто просто спрашивает разницу. - person Jon Skeet; 02.03.2012
comment
@Jon Skeet: Хорошо, я допускаю, что C# определил его как U+000A LINE FEED (но затем называет его новой строкой, что сбивает с толку, как U+0085 NEXT LINE). Во многих других контекстах (например, C и C++) \r — это символ, а \n — это заполнитель для концепции перехода к следующей строке. Я думаю, что чрезмерное упрощение путем объединения общей реализации (привязки с переводом строки) с новой концепцией строки приводит к недоразумениям и ошибкам. - person Adrian McCarthy; 03.03.2012
comment
@AdrianMcCarthy: Честно говоря, я бы предположил, что C и C++ здесь странные... - person Jon Skeet; 03.03.2012
comment
@Jon Skeet: Даже в C# \n отличается тем, что существует этап перевода runtime для преобразования в/из последовательности новой строки хост-платформы в текстовом режиме. Это делает \n отчетливо отличным от \r (и всех других последовательностей обратной косой черты). - person Adrian McCarthy; 03.03.2012
comment
@ Адриан: Нет, нет. Это просто персонаж. Если вам нужен терминатор строки для конкретной платформы, вы используете Environment.NewLine - person Jon Skeet; 04.03.2012
comment
@Jon Skeet: хорошо, значит, я ничего не знаю о C#. Тем не менее, поскольку мы не знаем языкового контекста, случайный читатель может ввести в заблуждение утверждение, что \n является переводом строки. - person Adrian McCarthy; 04.03.2012
comment
@AdrianMcCarthy: Но, по крайней мере, в C# и Java это это перевод строки. Это U + 000A, который в Unicode называется LINE FEED (и NEW LINE). Я отредактирую, чтобы упомянуть особый случай C и C++, но я искренне верю, что эти являются особыми случаями, а не наоборот. - person Jon Skeet; 04.03.2012

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

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

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

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

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

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

Во времена телетайпов и первых принтеров люди фактически воспользовались тем фактом, что это были две отдельные операции. Отправив CR без следующего за ним LF, вы можете напечатать строку, которую вы уже напечатали. Это позволяло использовать такие эффекты, как акценты, жирный шрифт и подчеркивание. Некоторые системы делали надпечатку несколько раз, чтобы пароли не были видны в печатном виде. На ранних серийных ЭЛТ-терминалах 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.

Почему разные системы выбрали разные методы? Просто потому, что не было универсального стандарта. Там, где ваша клавиатура, вероятно, говорит «Ввод», старые клавиатуры использовали «Возврат», что было сокращением от «Возврат каретки». На самом деле, на последовательном терминале нажатие клавиши «Ввод» фактически отправляет символ CR. Если бы вы писали текстовый редактор, было бы заманчиво просто использовать этот символ в том виде, в котором он пришел из терминала. Возможно, поэтому старые Маки использовали только 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!");, который звонит в колокольчик (или издает звуковой сигнал) и выводит сообщение. Но если бы я хотел затем напечатать что-то в следующей строке, мне все равно нужно было бы знать, что требуется хост-платформе для перехода к следующей строке вывода. КР ЛФ? КР? НЧ? NL? Что-то другое? Так много для портативности.

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

Отлично, а что за особый персонаж?

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

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

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

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

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

  • \r буквально означает возврат каретки.
  • \n — это магическое значение, которое преобразуется (в текстовом режиме) во время во время выполнения в/из семантики новой строки хост-платформы.
  • \r\n почти всегда является ошибкой переносимости. В текстовом режиме это преобразуется в CR, за которым следует последовательность новой строки платформы - вероятно, не то, что предполагалось. В двоичном режиме это преобразуется в CR, за которым следует некоторое магическое значение, которое может не быть LF — возможно, не то, что предполагалось.
  • \x0A — это наиболее переносимый способ обозначения ASCII LF, но вы хотите делать это только в двоичном режиме. Большинство реализаций текстового режима обрабатывают это как \n.
person Adrian McCarthy    schedule 03.03.2012
comment
Наткнулся на этот пост, пытаясь понять, как разделить ввод ‹textarea› в Python, и \r\n на самом деле единственный способ правильно разделить строки на отдельные элементы списка. Это заставляет меня задаться вопросом, является ли это каким-то странным артефактом HTML или это связано со способом, которым Python поглощает строку из моего объекта request. - person Pat Jones; 23.11.2019

  • "\r" => Возврат
  • "\n" => Новая строка или перевод строки (семантика)

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

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

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

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

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

hai

\n для новой строки.

person DAYA PHILIP    schedule 17.11.2012

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

person Josip Medved    schedule 14.08.2009
comment
В системах Mac OS X по умолчанию используется LF (поскольку он основан на BSD Unix). - person dreamlax; 15.09.2010

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

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

person Greg    schedule 14.08.2009

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

person Nathan Loding    schedule 14.08.2009

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

person wesley    schedule 18.04.2013

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

person Manjeet Kumar    schedule 09.10.2014