如果你在Linux環境底下用vi開啟DOS/Windows檔案的話,很有可能你在每行的結尾會看到一個『^M』的符號。若只是一般文字檔的話,只會造成閱讀的困擾,倒還沒有其他問題。但是如果是shell script 的話,這可會造成執行錯誤。對於第一次遇到這個問題的人,恐怕是一頭霧水。
為了瞭解這個問題,首先我們來看看Linux的每行結尾和DOS/Windows有什麼不一樣。我們做了兩個檔案:Linux 格式的linux_file和DOS格式的dos_file,分別用hexdump來看看檔案結尾。
首先是Linux的檔案,從紅色部分的標示可以看出來檔案結尾是十六進位的0x0a:
$ hexdump -C linux_file |
再來是DOS的檔案,從紅色部分的標示可以看出來檔案結尾是十六進位的0x0d 0x0a:
$ hexdump -C dos_file 00000000 44 4f 53 2d 66 6f 72 6d 61 74 20 66 69 6c 65 2e |DOS-format file.| 00000010 0d 0a 45 6e 64 65 64 20 77 69 74 68 20 30 64 20 |..Ended with 0d | 00000020 30 61 2e 0d 0a |0a...| 00000025 $ |
因為DOS的檔案格式比Linux的格式多了個0x0d,所以會在vi裡面多了一個^M的符號(M是第13個字母,而0x0d就是十進位的13).
0x0d 和 0x0a 這兩個十六進位值除了用控制字元來表示以外,通常也用跳脫字元(Escape character)的 \n 和 \r 來表示。 整理之後,可以得到以下這個表格:
行尾(end of line) 表示法 | ||||
檔案格式 |
十六進位 |
控制字元 (Control character) |
跳脫字元 (Escape character) |
ASCII 名稱 |
Linux |
0x0a |
^J |
\n |
LF |
DOS/Windows |
0x0d 0x0a |
^M ^J |
\r \n |
CR LF |
知道了Linux與DOS檔案格式的差別之後,要處理這個問題也就呼之欲出了。在Linux的shell 命令裡,有兩個簡單的方法可以消除這個^M。
第一種方法,是利用sed的替換命令,將\r換成空字元:
sed "s/\r//" dos_file > dos_file_linux |
第二種方法,是利用tr的刪除命令,將\r刪除:
tr -d "\r" < dos_file > dos_file_linux |
任何一種方法做完之後,DOS的行尾已經轉換成Linux行尾:
$ hexdump -C dos_file_linux 00000000 44 4f 53 2d 66 6f 72 6d 61 74 20 66 69 6c 65 2e |DOS-format file.| 00000010 0a 45 6e 64 65 64 20 77 69 74 68 20 30 64 20 30 |.Ended with 0d 0| 00000020 61 2e 0a |a..| 00000023 $ |
(2012/10/16 Update) 在某些系統上可能會有dos2unix這個方便的小程式,以下的例子把 DOS 格式的 a.txt轉換成Linux格式的b.txt
dos2unix a.txt b.txt
留言列表