那天在部署项目的时候,遇到了一个很奇怪的现象。我一度怀疑我的职业生涯结束了。后来经过排查,发现是Linux和Windows下shell脚本中的换行符。格式问题导致脚本无法执行...(至此,标题中提到的意外就结束了...:)看来是个愚蠢的问题,溜走:)...不过莎士比亚说的是解决问题的最好方法就是解决它。一个好的方法是下次不再这样做。于是我们追根究底,彻底搞清楚计算机系统中的换行符是什么。历史资料在计算机出现之前,有一种叫做电传打字机(TeletypeMode)的通讯设备,它每秒输出10个字符,平均每个字符耗时0.1秒,但有个问题是打一个字要耗费0.2秒新队。秒,在这个时间段内,如果有新的字符来了,就会丢失,所以为了解决这个问题,有人在每行后面加两个字符,表示行的结束。那么这里涉及到两个动作:将打印探针(如上图刻度上的表头)从右向左拉,也就是回车向左拉回不够,而探针必须被包裹(对应吐出一行纸的距离),这是换行(linefeed)背后的概念,已经被移动到电脑系统中。但是,有人的地方就有区别,各大系统已经开始显现。Windows系统中,每行结束为回车+换行(与上述两个动作一致),\r\n;在Unix系统中,每行末尾只有一个新行\n;在Mac系统中,每行末尾只有一个新行\n;PS:旧MAC系统使用\r,现在MAC系统使用\n,与Unix一致。不同系统之间的换行规则不同,导致不同系统下的文件交叉使用时不一致。比如最常见的就是Unix/Mac系统下的一个文件在Windows中打开时,所有的文字都会变成一行。原因很明显。.ASCII码二进制十进制十六进制字符/缩写说明00001001909HT(Horizo??ntalTab)水平制表符00001010100ALF/NL(LineFeed/NewLine)换行键00001011110BVT(VerticalTab)垂直制表符00001100120CFF/NP(FormFeed/NewPage)翻页键0000110CR(1130DCR)CarriageReturn)Enterkey00001110140ESO(ShiftOut)不用切换练习见实章下面一步步练习上面的内容,测试环境是Windows和Linux。Windows下新建一个win.txt文件,用通俗易懂的语言写一句话。听过上面讲座的同学应该知道,这里的换行符是CRLF。谈话很便宜,给我看你的代码。在linux系统中用vim打开新建的文件不是很正常吗?它与Windows上的显示相同。请注意,当vim查看文件时,它会检测换行符。如果所有的换行符都是CRLF,那么它会自动以dos格式显示文本内容,在最下面的[dos]中也有体现。dos(DiskOperatingSystem磁盘操作系统)和Windows一样使用CRLF。使用cat-A选项查看文本中的所有字符,可以看到^M$多了。^M是Linux等系统规定的特殊标记,占一个字符大小,不是^和M的组合,只能用Ctrl+v、Ctrl+m按下;而$不是换行符,可以理解为Linux下用来表示文本EOF结束的符号。使用cat-v选项显示非打印字符,去掉第一行的回车,然后查看sed-i'1s/^M//'win.txt,看到第一行的^M没了,第二行还是保留着。重复第一步以查看更改。结果发现vim中多了一个^M符号,左下角少了[dos]标识。这就回应了第二点提到的现象,也就是说vim使用linux来显示文本内容。至此,我们已经确认了Windows和Linux环境下换行规则不同带来的差异。验证回车符是否真实存在。看到社区里的朋友有这个尝试,我参考了一下,做了。它可以直观地反映什么是“回车”。还原上面的例子,cat-A查看所有字符sed-i'1s/.*/&ypm/g'win.txt在第一行末尾添加ypm,再次查看,发现上面执行的命令使用.*来匹配整个行中不包含换行符^M,所以在第一行末尾添加了ypm。当我用cat正常查看文本的时候,发现一个奇怪的东西,ypmcoveredtalk,怎么解释?我们要知道,cat在普通模式下输出文本内容时,会将^M解释为回车。这是可以解释的。遇到回车,就好像从右向左打印探针一样。ypm的四个字符正好覆盖了talk的四个字符。这直观地解释了回车是什么。HowtoAvoid说到如何避免这种差异,其实不同的方向有不同的方法,比如针对^M和文本格式的强制转换,但我个人认为不同系统之间可以解决根本问题.在编辑代码的时候,要注意这个格式问题,各大IDE都有自己的解决方案。删除回车cat-vwin.txt|tr-d'^M'>linux.txtorcatwin.txt|tr-d'\015'>linux.txtorcatwin.txt|tr-d'\r'>linux.txt在vim编辑器中输入:%s/^M//g或:setfileformat=unix终端命令转换dos2unixwin.txt摘要回车\r:CR(回车)newline\n:LF(换行)Windows系统遵循最原始的规则,即必须满足回车+换行,不能缺少或顺序交换,即\r\n在Unix系统中,遇到换行\n时,会执行回车+换行操作,回车符\r会显示为特殊字符^M。没想到这么简单的问题,这么麻烦,其实很多朋友都遇到过这个问题,而且社区里经常出现换行导致的“”。血案”,希望不要因为之前的程序员小哥的失误导致千万级的损失。在运维、DB等领域,这些“小问题”可能会被放大,所以它们还是需要注意的,虽然有很多方法可以避免,但是在写代码的初期,应该养成注意这一点,排查问题的习惯,有时候这也是一个方向。PS:可能有些地方不严谨,欢迎大家讨论,轻喷……参考http://www.ruanyifeng.com/blog/2006/04/post_213.htmlhttps://www.cnblogs.com/linuxnote/p/3753153.htmlhttps://blog.csdn.net/zhangguangyi888/article/details/8159601
