关于特殊字符:有什么区别 和 ?

What is the difference between
and
?



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


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

在"旧"打印机上,
将打印头送回到行的开头,
将纸张前进一行。因此,两者都必须在下一行开始打印。

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

更重要的是,Unix倾向于使用
作为行分隔符; Windows倾向于使用

作为行分隔符,而Mac(最多为OS 9)用于使用
作为行分隔符。 (Mac OS X是Unix-y,因此使用
;可能存在一些兼容性情况,但是使用了
。)

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

编辑:这是语言敏感的。例如,在C#和Java中,
总是表示Unicode U + 000A,它被定义为换行符。在C和C ++中,水有点混浊,因为其含义是特定于平台的。请参阅评论了解详情


在C和C ++中,
是一个概念,
是一个字符,而

(几乎总是)是一个可移植性错误。

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

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

  • 然后将打印头移回到行的开头
  • 把它移到下一行。
  • 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
  • 为什么不同的系统选择不同的方法?仅仅因为没有通用标准。你的键盘可能会显示"Enter",旧的键盘用来表示"返回",这是Carriage 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模式:二进制和文本。在二进制模式下,无论发送什么数据都按原样传输。但是在文本模式下,有一个运行时转换,可以将特殊字符转换为主机平台对新行所需的任何内容(反之亦然)。

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

    那么,这也是依赖于实现的,但是有一种与实现无关的方式来指定它:
    。它通常被称为"换行符"。

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


    与所有其他反斜杠文字不同,因为涉及两个映射。这个两步映射使得
    与甚至
    明显不同,这只是CR的编译时映射(或者底层字符集中最相似的控制代码)。

    这让许多C和C ++程序员兴奋不已。如果您要对其中的100个进行轮询,则至少99个会告诉您
    表示换行。这不完全正确。大多数(也许是全部)C和C ++实现使用LF作为
    的神奇中间值,但这是一个实现细节。编译器使用不同的值是可行的。实际上,如果主机字符集不是ASCII的超集(例如,如果它是EBCDIC),则
    几乎肯定不是LF。

    所以,在C和C ++中:


  • 实际上是一个回车。

  • 是一个神奇的值,它在运行时转换(在文本模式下)到主机平台的换行语义。
  • 几乎总是一个可移植性错误。在文本模式下,这会被转换为CR,然后是平台的换行序列 - 可能不是预期的。在二进制模式下,这会转换为CR,然后是一些可能不是LF的魔术值 - 可能不是预期的。

  • \x0A是表示ASCII LF的最便携方式,但您只想在二进制模式下执行此操作。大多数文本模式实现都会将其视为
  • 好。


    • " r"=>返回
    • " n"=>换行符或换行符
      (语义)

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

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


    用于指向行的开头,可以从那里替换文本,例如

    1
    2
    3
    4
    5
    6
    7
    8
    main()
    {
    printf("
    ab");
    printf("\bsi");
    printf("
    ha");
    }

    生成此输出:

    1
    hai


    适用于新行。


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


    除了@Jon Skeet的回答:

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


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


    r n是回程; n是新行(换行)...取决于操作系统的含义。阅读这篇文章,了解更多关于' n'和' r n'...之间的区别。


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