不同系统环境下的换行符

这两天连续遇到了两个因为在不同操作系统中换行符不同所带来的问题,导致花费了一定的时间和精力。虽然之前就一直知道不同操作系统使用的换行符不一样,但是当实际遇上这些差异带来的问题时,才会发现学习的必要性。

换行符

一般会使用转义字符作为换行字符,包括 \n \r \r\n

在不同的操作系统的文件系统中,会使用不同的字符作为换行符:

  • Linux:\n LF(Line Feed)
  • Mac OS:\r CR(carriage return)
  • Windows: \r\n CR/LF

当然这些对于换行符识别的差异主要还是出现文件系统对于文件的识别当中,实际的 coding 过程中一般都还是全部使用 \n 作为字符串当中的换行符。

踩坑

记录一下因为换行符不同所踩的坑。

JavaScript 油猴脚本解析

因为比较经常使用 Google Translate 翻译所看的文档,有挺多的复制待翻译内容到网页端上进行翻译的使用场景,但是 PDF 文档复制时会被换行符也一并复制,所以粘贴的时候原本成句的内容会被分成几段,当作几句话来处理,内容很可能不正确,需要手动删除。一两次还好,次数多了就很麻烦,于是写了一个油猴脚本,捕获 Google Translate 中的粘贴内容,把想要粘贴的内容去除换行符。

想法很简单,就在输入框元素中监听 paste 事件,当出现 paste 事件时,获取粘贴的内容,阻断粘贴的操作,并把输入框的值改为去除换行符后的粘贴内容。

第一次尝试没有效果,就在代码里面添加一些 log,来进行 debug,从控制台的输出看到脚本是可以捕获到要粘贴的内容,然后去除换行符后的输出内容也是正常的,但是这个去除换行符后的内容重新复制并粘贴到控制台输入时,却仍然会有换行现象。如果是在控制台中获取元素,用同样的语句移除换行符的话,功能也是正常的。

最终发现问题就在换行符上面,我从 pdf 中复制的文字中,换行符为 \r\n,而我去除换行符的操作为 replace('\n',' ')。当我去除了 \n 之后,网页端的解析还是当有换行符,在控制台的输入上面也还是有换行的作用,最终把去除换行符的语句改为 replace(/(\r\n|\r|\n)/g, ' '),套了个正则匹配所有类型的换行符,问题解决。

CMakeList

打算使用 LLVM 在 GitHub 中的代码仓库拉下来的源代码进行构建,在使用 CMake 的时候出现问题,提示问题在 cmake/config.guess 文件中,但是又完全没有说是什么问题,而且它提示的行号基本全是空行。搜了一下,发现这个问题出现得还挺多,不过别人的提示信息更多,提示是字符 \r 出问题,说的大概就是换行符不一致,给的方法是将文件的换行符转成 unix 的换行符即可。

下了一个工具 dos2unix 可以直接将文本文件的换行符转成 unix下的换行符,转换之后,cmake 就可正常运行,生成构建文件了。(尽管直到现在过了我都还没有成功 build 好 llvm 及其配套工具。)

Git

这个是之前遇到的问题了,在 Windows 系统下通过 Git 提交的文件,在使用 WSL 打开时,会提示每一个文件都有修改。在本地中同样的 repo,同样的历史记录,当前状态显示不一样。

这个可以通过设置 core.autocrlf 来解决,打开了这个选项之后,在提交时会把所有的 CR/LF 换行符转成 LF 换行符,在 checkout 代码时又会把文件中的 LF 换行符转成 CR/LF。本质就是统一在提交记录里使用 LF 作为换行符。