0%

换行符问题

一直不理解换行符,这次弄清楚。

  有时候在windows下的文件放到linux或者Mac下结尾会显示^M,而后两个系统的文件本来换行换的好好的,放到windows下又只显示一行,而且有乱码,这是怎么回事?
  这里涉及到两个字符,“回车”跟“换行”,先看看这两个的英文:

  • 回车: carriage return,缩写为CR
  • 换行: line feed,缩写为LF

关于“回车”和“换行”这两个概念的来历

  原本确认键这个术语用于打字机的扳手,若打字机的语言是由左至右书写的语言,回车用于将承载装纸滚筒的机架(carriage)移到最右边,以便令印字位置对准一行的开头,同时顺便滚动转筒,换到下一行(line feed)。最开始的打字机如下:

<img title=”打字机”src=”../img/crlf.png” width=”50%” height=”50%”>

  第一个有动力的回车功能在1960年由Smith Corona加入电打字机。因为在打字机上“回车”操作比“换行”操作更费时,“回车”就排在了“换行”前边。

  后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。做Unix的一般比较懒,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;Mac系统里,每行结尾是“<回车>”,即“\r”。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号:

<img title=”windows中的文件在mac下打开”src=”../img/crlf2.png” width=”50%” height=”50%”>

<img title=”mac中的文件在windows下打开”src=”../img/crlf3.png” width=”50%” height=”50%”>

其他地方的换行

  上边说的是在不同操作系统中,系统默认的换行符。在C语言中,用转义字符”\n”来表示换行:

1
printf("Hello\nworld");

在输出到文件中时,C语言会根据不同的系统将换行符转换成不同的字符。比如上一句在windows中和在mac中各显示如下:

C在不同系统中输出换行符

  在HTTP协议中,使用”\r\n”表示断句:

1
2
3
4
GET / HTTP/1.1\r\n
Host:10.211.55.5\r\n
Connection:close\r\n
\r\n
因此nginx中也就有了这两个定义:
1
2
3
4
5
6
7
8
9
// 在ngx_core.h中
#define LF (u_char) 10
#define CR (u_char) 13
#define CRLF "\x0d\x0a"

// 在ngx_files.h中
#define ngx_linefeed(p) *p++ = LF;
#define NGX_LINEFEED_SIZE 1
#define NGX_LINEFEED "\x0a"

ngx_core.h中定义的用于HTTP协议中的换行,在ngx_files.h中定义的用于输出文件

现在的编辑器一般都可以自己设定换行符,比如sublime text:

还有atom:

总结一下

  现在我们知道最早的回车换行来自机械打字机,后来到电传打字机,再到ASCII,最后到各种操作系统,就形成了我们现在看到的”回车”跟”换行”。

使用情景 各种换行符
机械打字机 手动先回车,后换行
电传打字机 电动回车换行
ASCII 回车:015 13 0D CR '\r' (carriage ret)
换行:012 10 0A LF '\n' (new line)
操作系统 windows: CRLF
linux: LF
mac(至版本9): CR
mac(OS X EI Capitan,10.11.3): LF
C语言 转义字符”\n”
HTTP协议 CRLF表示断句
各种编辑器 可以自己设置换行符

参考

  1. 这个讲的比较乱: http://blog.csdn.net/tskyfree/article/details/8121951
  2. 一个小故事: http://www.cnblogs.com/faraway/archive/2009/03/05/1403649.html
  3. 为什么CR在前,以及机械打字机:[https://www.zhihu.com/question/21245110/answer/30431335](- https://www.zhihu.com/question/21245110/answer/30431335)
  4. wiki回车符:https://zh.wikipedia.org/wiki/%E5%9B%9E%E8%BD%A6%E7%AC%A6
  5. wiki换行符:https://zh.wikipedia.org/wiki/%E6%8F%9B%E8%A1%8C