\r和\n有什么区别?

\r\n有什么不同?我认为这与Unix、Windows和Mac有关,但我不确定它们到底有什么不同,以及在正则表达式中搜索/匹配哪个。

313036 次浏览

他们是不同的角色。\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++中,水有些浑浊,因为其含义是特定于平台的。详见评论。

\r是回车;\n是换行(换行)…这取决于操作系统。关于'\n'和'\r\n'的更多区别,请阅读这个文章…在C。

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

除了@Jon Skeet的回答:

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

  • "\r" =>返回
  • "\n" =>换行或换行 李(语义)< / p > < / >

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

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

在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。
  • 旧的IBM系统在NL上使用了标准化的EBCDIC——一个在ASCII字符集中甚至不存在的字符。在Unicode中,NL是U+0085 NEXT LINE,但实际的EBCDIC值是0x15

为什么不同的系统选择了不同的方法?很简单,因为没有统一的标准。你的键盘上可能显示的是“Enter”,而旧的键盘上显示的是“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低频?CR吗?低频?问吗?别的吗?这就是便携性。

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

很好,那么这个特殊的角色是什么?

好吧,这也是依赖于实现的,但是有一种与实现无关的方式来指定它:\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那样对待它。

\r用于指向一行的开始,并可以替换从那里开始的文本。

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

产生如下输出:

hai

\n表示换行。

在c#中,我发现他们在字符串中使用\r\n。

\r用于回车。(ASCII值为13) \n用于新行。(ASCII值为10)