浅谈CR,LF和CRLF

引入

以Pycharm为例:
在这里插入图片描述
点击CRLF,有三个可供选择:
在这里插入图片描述
在这里插入图片描述
其实注释的很明白:

  • CR用于MacOS下,作用相当于 \r
  • LF用于Unix和macOS下,作用相当于 \n
  • CRTF用于Windows下,作用相当于 \r\n

是什么

一言以蔽之:不用平台下Enter键对应的编码。
我们知道,我们通过键盘的输入文本,而这些文本都是按照一定编码集存储在计算机中的,如输入“12”这个数, 其实计算机存储的是“1”的ASCII码——49,“2”的ASCII码——50(假设使用的是UTF编码(前128照搬ASCII码)),而当我们按下Enter键,计算机存储的也是ASCII码,但是奇妙的是,不同于一般的字符——0-9和A-Z等,Enter键对应的ASCII码在不同的操作系统中是不一样的
在这里插入图片描述
参考:ASCII码表和转义字符

就如同上一节看到的那样:

  • CR用于Mac下,作用相当于 \r
  • LF用于Unix下,作用相当于 \n
  • CRTF用于Windows下,作用相当于 \r\n

那么意思其实很明显了,当我们选择CRTF进行开发或文本编辑,则我们按下的Enter键将会被存储为 \r\n,一般而言这是Windows的默认存储方式,其他两种类似的道理。 至于为什么MacOS会有两个表示方式,这是因为老Mac上(Mac OS)Enter键代表 \r,后来Mac投奔了Unix阵营(Linux就不用说了,嫡系),Mac OS X下,Enter键也代表 \n 了。

为什么

先看一下英文:

  • CR:\r,Carriage Return,车回 —— 回车
  • LF: \n,Line Feed,行喂 ——喂行
  • CRTF:\r\n,Carriage Return Line Feed,回车+喂行

说到根源,还得追溯到打印机时代,现代电脑键盘其实是由以前的打印机键盘演变而来,这里说的打印机是老式手动打印机不是现代油墨打印机,为了简便起见,我们把这种老式打印机简化为三个部件:键盘,打印针头和纸。
打印机工作时是这样的:按下不同的键则切换对应的打印针头(不同的字符),打印时针头从左往右打印。当打印到一行末尾时要进行换行,换行分为两步:

  1. 将打印针头跳整到行头(最左侧)
  2. 将纸往上移动一行

打印针头就叫字车——Carriage,将字车调整到行头,就叫Carriage Return —— 回车,而将纸往上移动一行,相当于准备好了新的空白行,就等待打印针头打印了,形象地称为 —— Line Feed,换行。
这么捋下来Enter键应该存储为 \r\n 比较合适,因为最能还原真实操作嘛,但是坏就坏在统一标准还没建立时,有的平台(不单单指计算机,也有打印机,驱动软件等等)故作聪明,将 \n\r 自动转化为 \r\n,所以有的操作系统就直接使用 \n\r了,到了建立标准时,又依据市场实际情况制定了不同的标准(IT行业经常是这样)。。。不同平台又遵循不同的标准,更不要提有的根本不鸟标准。
一句话,木已成舟,谁都不care谁,到了现在也还是各行其是。
当然,当年的恩恩怨怨纠结难清,感兴趣的话大家可以自己查询,这里放一个有趣讨论的链接:
Unix/Linux/Mac 与 Windows 的换行符不统一的原因/目的是什么
无论当年是什么原因导致大家互不相让,现实是:三大平台的Enter键码的确不一样,唯一的好消息是新Mac OS X丢弃了原来的 \r,转用了Unix阵营—— \n ,所以现在市场上实际上就两个:\r\n 的CRLF和 \n 的LF。

有什么关系呢

乍一看来没什么问题,但是想一下,一篇Mac上的优美诗歌,传到Windows上就只剩了一行。更不要说团队里进行协同开发,试想一下三个人使用三个平台通过Git修改同一份文件,如果不经过任何转换,则三个人每次提交的文件都和之前的文件冲突(假设最近一次修改不是自己)—— Enter的键码不一样。
为了解决这个问题,IDE提供了这样一个跨操作系统的功能:自定义Enter的键码。
回到之前的问题,现在三个人都约定好:我们将IDE的换行方式都设置为CRLF进行开发,这样提交git就不会冲突了。
但是,在实际开发中,这其实是不实用的,去约定不同平台下每个人的开发习惯不安全也不方便。所幸Git本身提供这样的功能:在本地库和远程库中对Enter的键码进行转换。

设置core.autocrlf

Git有个core.autocrlf属性:

git config --global core.autocrlf XXX

这个core.autocrlf属性有三个值(即XXX的取值):

  • true:拉取时总是将本地仓库换行方式转化为LF(\n)存储至远程仓库,拉取时总是将远程库LF(\n)转换成本地库换行方式。
  • false:不做转换,总是提交本地换行方式,总是拉取远程库换行方式。
  • input:提交时总是将本地仓库换行方式转化为(\n)存储至远程仓库,拉取不做转换。

关于不同的平台怎么设置这个值,其实没有统一标准,但是一个约定俗成的做法是:保证远程库中的换行方式总是LF(\n)。
依据这个原则:

  • Windows下该值设置为true,这样可以保证提交时总是将CRLF(\r\n)转换为LF(\n),保存在远程库中,拉取(签出)时总是将LF(\n)转化为CRLF(\r\n),符合Windows习惯。
  • Mac/Unix下设置为input,Mac/Unix本地默认的换行方式就是LF(老Mac是CR,现在的Mac已经变成了LF),所以理论上可以设置为false,即提交拉取都不用作转换,但是为了防止Mac不小心提交了一个Windows下的文件(例如直接接收Windows文件进行的修改等等),一般将该值设置为input,即提交时总是作转换——如果有CRLF则转换为LF,拉取时不用转换。

总结上面可以看到两个原则:

  • 总是保证远程库中Enter键编码是LF(\n
  • 总是保证“”的安全性 :本地库—>远程总是要做转换,而读则根据本地需要而定

当然,也能知道以下做法原则上也没问题:

  • Mac/Unix下设置为true也没问题,只是拉取时会作无谓的检查 —— 是否是LF(\n),影响效率
  • 如果团队里全部用的都是一个平台(如Windows),则全部设置为false也没问题

core.autocrlf具体属性介绍可见 git core.autocrlf配置说明

PS:

  1. 全文我都使用Enter键来代指通常所说的“回车键”或“换行键”,这样尽量避免语言带来的困惑,细心的话,可以看到之前放上的ASCII码表中,\r叫回车键,\n叫换行键,是不一样的。
  2. 在实际使用中,Mac上一首优美的诗歌文件传到Windows下打开通常没有换行失败的烦恼,这是因为打开的软件自动检测并做了转换,无论是本机软件还是第三方如notepad,或是甚至是QQ聊天框这种应用,只是我们没有注意到而已。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值