\ r和\ n有什么区别?


245

如何\r\n不同?我认为这与Unix vs. Windows vs. Mac有关,但是我不确定它们之间到底有什么不同,以及在正则表达式中搜索/匹配哪些。


1
这需要一个语言标签。不同的语言对'\n'
Adrian McCarthy 2014年

Answers:


383

他们是不同的角色。\r是回车符,\n是换行符。

在“旧”打印机上,\r将打印头送回该行的开头,并将\n纸张前进一行。因此,都需要在下一行开始打印。

显然,这现在已经无关紧要了,尽管取决于控制台,您仍然可以使用它\r来移至该行的开头并覆盖现有文本。

更重要的是,Unix倾向于\n用作行分隔符。视窗倾向于使用\r\n作为行分隔和Mac(最多OS 9)用于使用\r作为行分隔符。(Mac OS X是Unix-y,因此可以\n代替使用;不过,在某些兼容性情况下,\r可以代替使用。)

有关更多信息,请参阅Wikipedia换行文章

编辑:这是语言敏感的。例如,在C#和Java中,\n 始终表示Unicode U + 000A,它定义为换行符。在C和C ++中,水有些混浊,因为含义是特定于平台的。有关详细信息,请参见评论。


22
老人+1。终端输出用于直接控制精美的电子终端(在那些精美的CRT显示器之前的TTY)。因此,我们得到了关于回车符和换行符(如Jon Skeet所述,可能需要两者)和\ a“ bell”,\ b“ backspace”(不要与“ delete混淆”)中的那些东西的奇妙制品。 ”,以及与tty通信所需的所有其他控制字符。
erjiang

35
老人+1。您仍然可以在Windows命令提示符下按Ctrl + G,按Enter,PC扬声器将发出蜂鸣声。那是古代留下的。
戴夫·卡莱尔

@Crappy编码的家伙真的吗?在Vista上,它只是说“不被识别为内部或外部命令”
Ponkadoodle

2
@AdrianMcCarthy:当然,这里的问题实际上并未指定 C或C ++。在C#,例如\n 保证是换行(节2.4.4.4)。当然,如果OP指定了平台,那就太好了……此外,我认为,这种详细程度对于那些只是要求差异的人而言,比起使用更容易造成混乱。
Jon Skeet 2012年

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)将打印头移回该行的开头。(Unicode将其编码为U+000D CARRIAGE RETURN。)
  • \x0A(LF)将打印头向下移动到下一行。(Unicode将其编码为U+000A LINE FEED。)

在电传打字机和早期技术的打印机时代,人们实际上利用了这是两个独立的操作这一事实。通过发送CR而不跟随LF,可以在已经打印的行上打印。这允许重音,粗体和下划线等效果。某些系统多次套印,以防止密码在硬拷贝中可见。在早期的串行CRT终端上,CR是控制光标位置以更新屏幕上已有文本的方法之一。

但是大多数时候,您实际上只是想转到下一行。某些系统不需要一个控制字符,而只允许一个或另一个。例如:

  • Unix变体(包括Mac的现代版本)仅使用LF字符来表示换行符。
  • 旧的(OSX之前的)Macintosh文件仅使用CR字符来表示换行符。
  • VMS,CP / M,DOS,Windows和许多网络协议仍然期望两者:CR LF。
  • 使用EBCDIC的旧IBM系统在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有几个转义序列来表示控制代码:

  • \a (用于警告)会打响电传铃声或使终端发出蜂鸣声
  • \f (用于换页),移至下一页的开头
  • \t (用于标签)将打印头移至下一个水平标签位置

(此列表有意不完整。)

这种映射发生在编译时 -编译器看到\a并放置了用于魔术的任何神奇值。

请注意,大多数助记符都与ASCII控制代码直接相关。例如,\a将映射到0x07 BEL。可以为使用ASCII字符以外的其他字符作为主机字符集的系统(例如EBCDIC)编写编译器。具有特定助记符的大多数控制代码都可以映射到其他字符集中的控制代码。

晕!可移植性!

好吧,差不多。在C语言中,我可以写出printf("\aHello, World!");铃声(或嘟嘟声)并输出一条消息。但是,如果我想在下一行中打印某些内容,那么我仍然需要知道主机平台转移到下一行输出所需要的内容。CR LF?CR?如果?NL?还有吗 便携性非常重要。

C有两种I / O模式:二进制和文本。在二进制模式下,无论发送什么数据,都按原样发送。但是在文本模式下,有一个运行时翻译,可以将特殊字符转换为主机平台换行所需的内容(反之亦然)。

太好了,那么特殊字符是什么?

嗯,这是实现相关的,太多,但有一个独立于实现的方式指定它:\n。通常称为“换行符”。

这是一个微妙但重要的要点: \n编译时映射到实现定义的字符值(在文本模式下),然后在运行时再次将其映射到基础平台移动所需的实际字符(或字符序列)到下一行。

\n与所有其他反斜杠文字不同,因为涉及两个映射。这种两步映射\n与even相比有很大不同,even \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

试图弄清楚如何在Python中分割<textarea>输入时遇到了这篇文章,这\r\n实际上是将行正确分割成单独的列表元素的唯一方法。这让我想知道这是否是一些奇怪的HTML工件,或者它是否与Python从request对象中提取字符串的方式有关。
帕特·琼斯

11
  • “ \ r” =>返回
  • “ \ n” =>换行符或换行符(语义)

  • 基于Unix的系统仅使用“ \ n”结束一行文本。

  • Dos使用“ \ r \ n”结束一行文本。
  • 其他一些机器仅使用“ \ r”。(Commodore,Apple II,OS X之前的Mac OS等)。

5

\r 用于指向一行的开头,并且可以从此处替换文本,例如

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

产生以下输出:

hai

\n 用于换行。


4

简而言之,\ r的ASCII值为13(CR),\ n的ASCII值为10(LF)。Mac使用CR作为行定界符(至少,以前做过,对于现代Mac我不确定),* nix使用LF,Windows同时使用(CRLF)。


1
Mac OS X系统默认使用LF(因为它基于BSD Unix)。
dreamlax

3

除了@Jon Skeet的答案:

传统上,Windows使用\ r \ n,Unix \ n和Mac \ r,但是较新的Mac使用\ n,因为它们基于unix。




By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.