\ r和\ n有什么区别?

时间:2009-08-14 19:37:23

标签: special-characters line-endings

\r\n有何不同?我认为它与Unix与Windows与Mac有关,但我不确定它们是如何不同的,以及在正则表达式中搜索/匹配的内容。

9 个答案:

答案 0 :(得分:353)

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

在“旧”打印机上,\r将打印头发送回行的开头,\n将纸张前进一行。因此,两者都必须在下一行开始打印。

显然现在这有点不相关,虽然取决于控制台,您仍然可以使用\r移动到行的开头并覆盖现有文本。

更重要的是,Unix倾向于使用\n作为行分隔符; Windows倾向于使用\r\n作为行分隔符,使用(使用使用作为行分隔符使用\r。 (Mac OS X是Unix-y,因此使用\n代替;但可能存在一些兼容性情况,但使用\r代替。)

有关详细信息,请参阅Wikipedia newline article

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

答案 1 :(得分:88)

在C和C ++中,\n是一个概念,\r是一个字符,而\r\n(几乎总是)是一个可移植性错误。

想想一个旧的电传打字机。打印头位于某些线上和某些列中。将可打印字符发送到电传打字机时,它会在当前位置打印字符并将打印头移动到下一列。 (这在概念上与打字机相同,只是打字机通常相对于打印头移动纸张。)

如果您想完成当前行并从下一行开始,则必须执行两个单独的步骤:

  1. 将打印头移回行首,然后
  2. 将其移至下一行。
  3. 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。
    • 在NL上标准化使用EBCDIC的旧IBM系统 - 在ASCII字符集中甚至不存在的字符。在Unicode中,NL为U+0085 NEXT LINE,但实际的EBCDIC值为0x15

    为什么不同的系统选择不同的方法?仅仅因为没有通用标准。你的键盘可能会说"输入",旧的键盘用来说"返回",这是Carriage Return的缩写。实际上,在串行终端上,按Return实际上会发送CR字符。如果你正在编写一个文本编辑器,那么从终端进入该字符就很有诱惑力。也许这就是为什么旧版Mac只使用CR。

    现在我们已经standards,有更多方式来表示换行符。虽然在野外非常罕见,但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。它通常被称为"换行符#34;。

    这是一个微妙但重要的一点: \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

答案 2 :(得分:10)

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

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

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

答案 3 :(得分:4)

简而言之,\ r \ n具有ASCII值13(CR),\ n具有ASCII值10(LF)。 Mac使用CR作为行分隔符(至少,它之前做过,我不确定现代的mac),* nix使用LF,Windows使用两者(CRLF)。

答案 4 :(得分:4)

\r用于指向一行的开头,可以替换那里的文字,例如

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

生成此输出:

hai

\n适用于新行。

答案 5 :(得分:3)

除了@Jon Skeet的回答:

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

答案 6 :(得分:2)

\ r \ n是回程; \ n是新行(换行)...取决于操作系统的含义。请阅读此article,了解有关“\ n”和“\ r \ n”...之间差异的更多信息。

答案 7 :(得分:2)

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

答案 8 :(得分:1)

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