不同作業系統的換行字元

不同作業系統對的「換行」在文字檔案中的表示方式有一些差異,
以常見的 windows, mac 以及 linux 來說,使用到了 ASCII 字元集的兩個,分別是 LFCR

LF, CR 的意思

這兩個詞分別來自於傳統打字機的兩個行為,將打字的位置移到最左邊,以及將紙捲動,讓字輸出到到下一行。

LF

全稱是: Line Feed ,表示將印字頭往下一行,有些時候會寫成 NL,也就是 New Line 新一行的意思。
在許多程式上用 \n 表示,也可以用 Ctrl + M^M 來表示。

CR

全稱是 Carriage Return ,表示將印字頭移回一行的最左邊,也就回到起點(return),
在許多程式上用 \r 表示,也可以用 Ctrl + J^J 表示。

不同系統的差異

不同作業系統對於換行的表示方式如下表。

作業系統 使用字元 程式表示
windows CR+LF \r\n
unix/linux LF \n
Apple 系列 CR \r

在 macOS X 之後,換行字元也跟 unix/linux 一樣使用 LF 了。

由字面的意思來看, windows 的作法算是忠於傳統了,完整地描述整個輸出位置的 歸位到下一行

不過在電腦剛出現,記憶體資源非常稀少、珍貴的年代,使用一個字元表示換行,是較為經濟的作法。

造成的問題

windows 編輯 linux 開啟

在 windows 下所儲存的檔案,由於使用了 \r\n 來表示換行,
因此由 windows 所編輯的文字檔案,拿到 linux 底下開啟,
其中的 \n 會被解析為換行,而前頭的 \r 則會被視為一個 ASCII 字元,
由於無法直接顯示(非一般像 abc123 這種可視字元),會被轉換成等義的 Ctrl + M
Ctrl 常被用 ^ 表示,因此會在行尾看到一個 ^M 的符號。

對於一般的文字資料而言,只是讓人看得覺得的礙眼,
但如果換到程式碼析的場景上,這個多出來的 ^M 字元就有可能造成語法錯誤。
之前提到 ^M 實際上是個不可見字元,所以出錯的時候排查會變得困難。

記得那時候編寫程式都得注意在編輯上設定使用 linux 的模式進行換行處理,
哪天沒注意到,程式可能直接掛掉給你看。也因此那時候無法作設定的 windows 記事本,
非到莫可奈何或是程式只在 windows 底下跑的狀況,是不拿出來使用的。

這個問題與跟後來 windows 在 UTF-8 文字檔頭,加上特殊字元 BOM 造成的狀況一樣惱人。

linux, mac 編輯 windows 開啟

而在 linux, mac 下編輯的文字檔案,拿到 windows 下開啟的時候,
則會由於單獨的 \r\n 並不能表示換行,因此換行的地方會出現一個方框 類的文字。
因為沒有換行,所有的內容都會黏在一起。

個人曾經在不知道原因的狀況下,在 windows 下手動一行一行處理,還好檔案不是很大。

linux v.s. mac

可能是很晚才接觸 mac ,所以不曾遇到過。又或著可能 mac 系統是來自於同為 unix-like 的 BSD 系列。
所以還不曾遇過 linux 編的檔案在 mac 上顯示錯誤,反之亦然。
不過隨著新一代的 mac 作業竹糸統也採用 LF 作為換行字元,兩者之間的文字顯示,
應該更難遇到換行字元不同照成格式跑掉的問題。

其它的影響

無論結果是讓多行變成一行,或是多出現的 ^M ,除了造成程式執行上的錯誤之外,
在不同系統下編輯的轉換,也會造成資料的異動,在版本管理上相同內容,換行字元不同下被視為新的版本。

因此像 git 就有機制,傳入純文字資料,會先統一轉成一致的格式,來確保不會產生多餘的版本。
這算是一個很方便的機制,讓使用不同作業系統的開發者,能方便的分享程式碼。

但是 git 的模式不見得每個都有幫助,隨著 windows 不區分檔名大小寫而加入的 git 特性,倒是曾經造成我一些麻煩。

結語

個人經驗中, windows 一直是包袱很重的作業系統,這種影響層面很大的改變是很難發生的,
直到現在用 windows 10 作業系統,處理中文字還是有許多地方依系統語系使用當地字集,繁中是使用 Big5 字集來看,
很難看到某天的 windows 全面改用 LF 作為換行字元。

雖然主流的文字編輯器,程式整合開發環境幾乎都支援不同換行字元的處理。
不過不時還是會出現因為它導致程式出錯,無法順利的狀況發生,是從事程式相關工作得注意的地方。

參考資料

File format - Vim Tip Wiki
【详解】回车 换行 0x0D 0x0A CR LF \r \n的来龙去脉