回车与换行的一些历史
今天在写正则匹配换行符时,了解了一些回车和换行的历史,本来是在阮一峰的文章中看到的,后来又搜了下,发现一些细节有点分歧,而且国内的这种文章几乎都是复制粘贴的,本着探索精神,就去Google了好一会,最终在维基百科中找到了。
References:
- https://en.wikipedia.org/wiki/Newline#History 维基百科介绍的历史
- http://www.ruanyifeng.com/blog/2006/04/post_213.html 阮一峰文章
- http://feihu.me/blog/2014/end-of-line/ 知无涯之回车换行的故事
文章是我自己整理的,不保证完全正确,仅作参考,有错误欢迎指正。
现在的回车键按一下光标就会自动转到下一行开始,但在以前,回车(carriage return)和换行(line feed)是两个动作。
回车和换行,它们的出现要追溯到计算机出现之前,那时有一种电传打字机:Teletype Model 33 ASR
,如下图:
“车(carriage)”是指纸车,带着纸一起左右移动的模块。在早期的机械打字机上,打印头是固定的,只能通过左右移动纸车在一行上打字。当开始打第一个字之前,要把纸车拉到最右边,上紧弹簧,随着打字,弹簧把纸车拉回去。每当打完一行后,纸车就完全收回去了,所以叫回车。换行的概念就是:打字机边上有个"把手",往下扳动一下,纸会上移一行。在后来的电传打字机甚至今天的终端中都沿用了这些叫法。
YouTube上找了两个视频,一个是打印头固定的,一个是不固定的。可以看下,更容易理解:
在后来的电传打字机中,通常打印头可以左右移动,这样可以节省空间,同时也就没有纸车这个概念了,不过车这个说法依然留下来了,只不过是指打印头,回车即将打印头回到行首,换行依然是将纸上移一行。
然后就是关于回车(CR
)和换行(LF
)的顺序问题,据wiki记载,通常的电传打字机都是用CR+LF
这个顺序,典型的就是上面那台Teletype Model 33 ASR
。将换行分为两个功能隐藏了打印头不能在一个字符的时间内从最右侧移动到下一行开始的事实,这就是为什么CR
总是在LF
之前。在CR
之后打印的一个字符通常会变成污迹,由于打印头在移动到行首过程中,下个字符同时打印了。所以解决办法就是将换行做成两个字符:CR
将打印头移动到行首,LF
进纸。事实上,通常还要发送额外的字符(额外的CR
或者NUL
,这些字符将被忽略)以保证打印头有足够的时间移动到行首。
其实上面这段wiki的记载已经解答了大部分问题,剩下就是如今的计算机中表示问题,网上有很多这个问题的解释,我挑个觉得很合理的贴一下:
等到早期的计算机发明时,很自然的这两个概念被拿了过来。但是由于那时的存储设备非常昂贵,一些人认为在每行的结尾加两个字符用于换行,实在是极大的浪费,于是各个厂商在这一点上便出现了分歧。
由于一些早期的微型计算机还没有用于隐藏底层硬件细节的设备驱动,所以它们直接沿用了打字机的惯例,使用不带NUL
的CRLF
作为一个EOL
。而CP/M为了和这些微型计算机使用同一个终端,也采用了这种设计。所以它的克隆MS-DOS也同样使用CRLF
,由于Windows又是基于MS-DOS,为保持兼容性,所以就导致了如今的Windows是采用CRLF
作为EOL
,即\r\n
(或0x0D
0x0A
)。
而Multics在被设计之时就非常认真的考虑了这一问题,设计者们觉得只需一个字符便完全足够来表示EOL
,这样更加合理。那么选择CR
还是LF
呢?本来由于那时的键盘上都有一个Return
键,所以可能更好的选择是CR
。但当时考虑到CR
可以用来重写一行,以完成如粗体和删除线等效果,所以他们选择了稍稍难以理解的LF
。然后自己设计了一个设备驱动程序来将LF
转换为各种打字机所需要的EOL
,这个方案非常完美,当然除了LF
稍微奇怪一些。随后一脉相承的Unix
和Linux
们都继承了这个选择,于是你在这些操作系统上可以发现每一行的结尾是一个LF
,即\n(或0x0A)
。
Mac系统的选择就更加复杂一些。Apple在设计Mac OS时,他们采用了一个最容易理解的选择:CR
,即\r
(或0x0D
)。但这只维持到Mac OS 9,后一个版本的Mac OSX基于Mach-BSD内核,所以此后版本的Mac OSX在每行的结尾存储了与Linux一样的LF
,即\n
(或0x0A
)。
还有很多其它的操作系统采用更加不同的方案,这也导致了混乱的产生,文章开始提出的几个问题便由该混乱引起。因为Linux和Mac OSX上使用的是LF
,而Windows上使用的是CRLF
,那么Linux和Mac OSX上创建的文件在Windows上打开时,由于每一行的结尾只有一个LF
,但Windows只认识CRLF
,所以便不会有逻辑上的换行处理,故所有的文字被挤到了一行。反过来,如果Windows上的文件在Linux和Mac OSX上打开时,仅需LF
便可换行,那么每一行的结尾便多了一个CR
,对应的ASCII码为^M
。
而git的安装向导会特意有一个这样的提醒页面也出于此,因为一个项目可能有多个开发者,每个开发者可能使用的是不同的系统,那么开发者checkout代码时,如果不做换行符的转换,有可能就会出现只有一行或者行尾多了^M
的情况。当然,如果你有一个可以识别多种EOL
的现代文本编辑器,那么不做转换也无妨(notepad不行)。
更多细节请参考顶部“知无涯之回车换行的故事”的链接,我就不搬运了。
notepad++在win下可以通过设置显示行尾的结束符