Linux 中換行符問題


問題

Linux 環境執行一些腳本出錯,查找原因,發現是文件在Windows環境修改並上傳,格式被轉換為MS-Dos格式(換行符不同),這樣的文件在Linux中運行會出錯(shell 解釋器把換行符作為一個命令的提交)。

背景

很久以前,老式的電傳打字機使用兩個字符來另起新行。回車符(CR)把滑動架移回行首 ,換行符(LF)把紙上移一行 。

 

當計算機問世以后,存儲器曾經非常昂貴。有些人就認定沒必要用兩個字符來表示行尾。

UNIX 用 <LF> 一個字符來表示行尾。

Apple 的MacOS 9 及以前用 <CR> ,MacOS 10跟Unix一樣。

MS-DOS (以及Windows) 沿用老式的<CR><LF>,即敲一下回車鍵,相當於同時執行了 "回車+換行"。

總結一下:

系統 中文描述 英文描述 簡寫 轉義符
Windows 回車換行 Carriage Return and Line Feed CRLF \n\r
Unix/Linux/Mac OS 換行 Line Feed LF \n

如果你把一個文件從一種系統移到另一種系統,那么你就有換行符方面的麻煩。

Windows10的記事本(notepad)能夠自動識別Linux文件,但是在Linux中查看MS-DOS格式文件會發現每一行的末尾有個 ^M 字符。(^M 就是 <CR>)。

單個文件解決辦法

Linux 環境下 vim 直接編輯修改文件。

:set fileformat=unix

或者

:set ff=unix

保存退出就解決了。

批量文件解決方案一

這是通用方案,核心邏輯是

  • 找出文件:用file命令查看文件是否有特殊換行符
  • 修改文件:dos2unix命令直接改。(也可以vi 文件修改,后面在舉例)

具體例子

1. 檢查文件

$ file ./test.yml
./test.yml: ASCII text, with CRLF line terminators

輸出中看到了CRLF,這是Dos文件格式的標志。

2. 下一步,文件格式轉換

$ dos2unix ./test.yml
dos2unix: converting file ./test.yml to Unix format ...

3. 檢查文件是否真的修改了格式

$ file ./test.yml
./test.yml: ASCII text

發現沒有CRLF 標志,修改完成。

4. 把上面的命令合並,查找並修改Dos格式文件

$ find . -type f -exec file {} \; | grep CRLF | awk -F: '{print $1}' | xargs dos2unix
dos2unix: converting file ./ansible/README.md to Unix format ...
...

or

$ find . -type f -exec file {} \; | grep CRLF | cut -d : -f 1 | xargs dos2unix

批量文件解決方案二

從 7.1 版本后,dos2unix 有 -i, --info 參數,能夠直接獲取文件換行符的信息,我們能直接用這個命令來查找和替換。-ic 參數表示只是打印需要轉換的文件。

(MacOS 通過brew 可以安裝 dos2unix version 7.4,而centos 7 和 ubuntu 16 默認只能安裝版本6.0,更高版本需要自己單獨下載安裝包。)

$ dos2unix -i ./roy_test.yml
      11       0       0  no_bom    text    ./roy_test.yml
$ dos2unix -ic ./roy_test.yml
./roy_test.yml

上面的輸出數字 11 表示有11個dos換行符。

查找並修改dos文件:

$ find . -type f -exec dos2unix -ic {} \; | xargs dos2unix
dos2unix: converting file ./bin/Readme.txt to Unix format...
...

如果文件數量大,用xargs 替換 exec 更有效率,所以更好的命令是

$ find . -type f | xargs dos2unix -ic | xargs dos2unix

Windows開發中避免換行問題

使用編輯器Visual Studio Code

這個工具的右下角的文件格式確保是LF。如果不是,就點擊重新選擇。

 
1567752511438.png

gitbash 中設置默認檢入檢出換行符為linux(\n)風格

(為了團隊更好的協作)

開啟自動換行
$ git config --global core.autocrlf true

git config --global core.autocrlf true 簽出時將換行符轉換成CRLF,簽入時轉換回 LF
git config --global core.autocrlf input 簽出時不轉換換行符,簽入時轉換回 LF
git config --global core.autocrlf false 簽出簽入均不轉換

開啟安全換行
$ git config --global core.safecrlf true

解釋:
如果你把換行符搞亂了,在一個文件中既包含windows風格的換行符也包含unix風格換行符,那么 safecrlf 就可以發揮作用了:
git config --global core.safecrlf true 拒絕提交包含混合換行符的文件
git config --global core.safecrlf false 允許提交包含混合換行符的文件
git config --global core.safecrlf warn 提交包含混合換行符的文件時候給出警示

參考文檔

不同平台windows、linux、mac 上換行符的問題

vim下unix和dos格式轉換

NewLine Wikipedia



作者:華陽_3bcf
鏈接:https://www.jianshu.com/p/fe8ec5f5792d
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM