ある perl のプログラムをダウンロードした。 ここでは仮に hello.cgi とする。
$ perl -wc hello.cgi
hello.cgi syntax OK
$ chmod 755 hello.cgi
$ ./hello.cgi
bash: ./hello.cgi: No such file or directory
となって動かない。ところが
$ perl hello.cgi
Content-type: text/plain
Hello
ちゃんと動く。ここで疑うのは先頭の一行。
$ head -n 1 hello.cgi
#!/usr/local/bin/perl
perl のパスはあっている。どこかほかのところが関係しているのかと思い vim で行を削除したりするとなんか変。 削除したはずの行が復活したりするのだ。そこで直感したのは文字以外の制御文字が入っているということ。
$ head -n 1 hello.cgi | od -bc
0000000 # ! / u s r / l o c a l / b i n
043 041 057 165 163 162 057 154 157 143 141 154 057 142 151 156
0000020 / p e r l \r \n
057 160 145 162 154 015 012
0000027
あそうか Windows で使われることを前提とされているために"復帰"(carriage return) が入っていたのか。 上の出力結果では \r 8進数の 015 です。
$ tr -d '\015' <hello.cgi >tmp.txt
$ cp tmp.txt hello.cgi
以上のようにして \r を取り除きました。
Thu Oct 18 14:27:58 JST 2007
システム | 改行コード | 記号 | 8進数 | 16進数 |
---|---|---|---|---|
DOS (MS-DOS, Microsoft Windows) | CR+LF | \r+\n | 015+012 | 0x0D+0x0A |
UNIX (linux, FreeBSD, OS X, Solaris, AIX などのUNIXおよびUNIX系OS) | LF (Line Feed: 改行) | \n | 012 | 0x0A |
Mac (Mac OS Version 9まで) | CR (Carrige Return: 復帰) | \r | 015 | 0x0D |
line feed とは紙を必要な行だけ上に送る(下の行に印字装置が来る)の意。
carrige return とは紙を固定して移動する装置をもとの位置に戻す(紙の左端に印字装置が来る)の意。
コマンド | 例 | 説明 | |
---|---|---|---|
tr | tr -d '\r' < inputfile > outputfile | DOSをUNIXに変換 (CRを取り除く) | |
tr '\r' '\n' < inputfile > outputfile | MacをUNIXに変換 (CRをLFに置き換え) | ||
sed |
sed -e 's/\r$//' inputfile > outputfile
| DOSをUNIXに変換 (CRを取り除く) 注) FreeBSDでは不可 | |
sed -e 's/$/\r/' inputfile > outputfile
| UNIXをDOSに変換 (LFの前にCRを追加) 注) FreeBSDでは不可 | ||
awk | awk '{sub(/\r$/, ""); print}' inputfile > outputfile | DOSをUNIXに変換 (CRを取り除く) | |
awk '{sub(/$/, "\r"); print}' inputfile > outputfile | UNIXをDOSに変換 (LFの前にCRを追加) | ||
perl | perl -p -e 's/(\r\n|\n|\r)/\n/g' inputfile > outputfile | UNIXに変換 | |
perl -p -e 's/(\r\n|\n|\r)/\r\n/g' inputfile > outputfile | DOSに変換 | ||
perl -p -e 's/(\r\n|\n|\r)/\r/g' inputfile > outputfile | Mac(Version 9まで)に変換 | ||
nkf |
nkf -Lu -d inputfile > outputfile
nkf -Lw -c inputfile > outputfile nkf -Lm inputfile > outputfile 左のオプションに加えて以下のoutputfileの文字コードを指定する必要があります。
-j -s -e -w -w16 左から ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8N, UTF-16BE です。詳しくは‘man nkf‘で | UNIX(LF) DOS(CR+LF) Mac(CR) | |
ruby | ruby -e 'while gets; gsub(/\r\n|\n|\r/, "\n"); print; end' inputfile > outputfile | UNIX(LF) | |
ruby -e 'while gets; gsub(/\r\n|\n|\r/, "\r\n"); print; end' inputfile > outputfile | DOS(CR+LF) | ||
ruby -e 'while gets; gsub(/\r\n|\n|\r/, "\r"); print; end' inputfile > outputfile | Mac(CR) | ||
python | python -c "import sys,re;[sys.stdout.write(re.sub('\r\n|\n|\r', '\n',line)) for line in sys.stdin]" < inputfile > outputfile | UNIX(LF) | |
python -c "import sys,re;[sys.stdout.write(re.sub('\r\n|\n|\r','\r\n',line)) for line in sys.stdin]" < inputfile > outputfile | DOS(CR+LF) | ||
python -c "import sys,re;[sys.stdout.write(re.sub('\r\n|\n|\r', '\r',line)) for line in sys.stdin]" < inputfile > outputfile | Mac(CR) | ||
PHP | php -r 'echo str_replace(array("\r\n","\n","\r"), "\n", file_get_contents($argv[1]));' inputfile > outputfile | UNIX(LF) | |
php -r 'echo str_replace(array("\r\n","\n","\r"),"\r\n", file_get_contents($argv[1]));' inputfile > outputfile | DOS(CR+LF) | ||
php -r 'echo str_replace(array("\r\n","\n","\r"), "\r", file_get_contents($argv[1]));' inputfile > outputfile | Mac(CR) | ||
FreeBSD の sed は \r を CRと解釈しないので、改行コードの変換は以下のようにします。ここで ^M は実際の制御文字で、Ctrlを押しながらvを押した後にCtrlを押しながらmを押します。
sed -e 's/^M$//' inputfile > outputfile # DOSをUNIXに変換 sed -e 's/$/^M/' inputfile > outputfile # UNIXをDOSに変換
エディタ | コマンド | 説明 |
---|---|---|
※ 残念ながら改行コード(UNIX,DOS)が混在しているファイルには使えません。
※ vimはvi互換エディタの一つで、多くのlinuxディストリビューションではviは vimへのシンボリックリンクとなっている。 ※ MS Windows上で編集された文書をUNIX系OS上で開いた場合文字化けして 編集できないことがあります。例として丸囲い数字(丸数字)、ローマ数字などを 含む文書です。 | ||
vim | :++e fileformat=dos | 改行コードをDOSとして読み直す |
:set fileformat=unix | UNIXに変換 | |
:set fileformat=dos | DOSに変換 | |
:set fileformat=mac | Macに変換 |
エディタ | コマンド | 説明 |
---|---|---|
※ M-x はEscキーを押してすぐに x を押す。C-x はCtrlキーと同時にxを押す。
RET はエンターキーを押す。 ※ 改行コードと同時に文字コードも変換できる。 M-x set-buffer-file-coding-system RET utf-8-unix M-x set-buffer-file-coding-system RET shift_jis-dos M-x set-buffer-file-coding-system RET undecided-mac undecided は文字コードは変換しないの意味。C-x C-s で上書き保存。 C-x C-c でemacs終了。C-g はコマンドの取り消し。 | ||
emacs | M-x set-buffer-file-coding-system RET unix C-x RET f unix | UNIXに変換 |
M-x set-buffer-file-coding-system RET dos C-x RET f dos | DOSに変換 | |
M-x set-buffer-file-coding-system RET mac C-x RET f mac | Macに変換 |
※rfc959 は1985年10月に公開された File Transfer Protocol(FTP)の公式な仕様。インターネットにおける技術仕様や標準化の母体となる文書はInternet Engineering Task Force(IETF)やInternet Society(ISOC)などで、広く意見を求めるという意味でRFC(A Request for Comments)という一連の文書として公開されている。 | ||
転送モード | rfc959の記述 | 例 |
---|---|---|
ascii | 3.1.1.1. ASCII型 送信側は、データを内部文字表現形式から、標準的な8ビットNVT-ASCII 表現形式に変換する(Telnet仕様を参照)。受信側は、標準形式からその 内部形式に変換する。 |
WindowsからUNIX系サーバにテキストファイルをアップロードする場合、 改行コード\r\n が \n に変換される。 UNIX系サーバからWindowsにテキストファイルをダウンロードする場合、 改行コード\n が \r\n に変換される。 |
binary | 3.1.1.3. イメージ型 データは転送のため8ビットにまとめられ、連続したビットとして,送信 される。受信側コンピュータはデータを連続したビットとしてそれを 蓄積しなければならない。 |
データは改変されない。 テキスト以外に使用。 |
改行コードに加えて是非書き留めて置かなくていはいけないとがあります。それは文字コードがUTF-8の場合、そのファイルがBOM(Byte Order Mark)ありかBOM無しかということです。
> head -c 12 BOM.html | od -c -t x1 0000000 357 273 277 < ! D O C T Y P E ef bb bf 3c 21 44 4f 43 54 59 50 45 0000014
ファイルの先頭に8進数で、357 273 277 16進数で ef bb bf のバイナリーデータが付加されていることが確認できます。このためにVim バージョン6.x では文字化けしてしまいます。またW3C Markup Validation Serviceでは以下のような警告が出ます。
Byte-Order Mark found in UTF-8 File.
The Unicode Byte-Order Mark (BOM) in UTF-8 encoded files is known to cause problems for some text editors and older browsers. You may want to consider avoiding its use until it is better supported.
文字コードがUTF-8のファイルに付加されたバイトオーダーマーク(BOM)はいくつかのテキストエディターや古いブラウザでは問題を起こすことが知られているとの事です。困ったことにBOMなしの場合逆に文字化けを起こしてしまうアプリもあるので要注意です。いくつかのエディターではファイルを保存する時、UTF-8(BOMあり)、UTF-8N(BOMなし)で選択できるようになっているようです。以下にperlで先頭のバイナリーデータを取り除くことができるかどうかのテスト例。(※ コマンドの先頭の``>''はpromptで、タイプするものではありません。)
> head -c 12 BOM.html | perl -pe 's/\357\273\277//' | od -c -t x1 0000000 < ! D O C T Y P E 3c 21 44 4f 43 54 59 50 45 0000011 > head -c 12 BOM.html | perl -pe 's/\xef\xbb\xbf//' | od -c -t x1 0000000 < ! D O C T Y P E 3c 21 44 4f 43 54 59 50 45 0000011
nkf(Network Kanji Filter)でもBOMを取り除くことができます。タイプミスの心配が少ないです。※ nkf バージョン2.06 は不可、2.08 可。
> nkf --version
Network Kanji Filter Version 2.0.8 (2007-07-20)
> head -c 12 BOM.html | nkf -w | od -c -t x1
0000000 < ! D O C T Y P E
3c 21 44 4f 43 54 59 50 45
0000011
in-placeで文字コードUTF-8のBOMありhtmlをBOMなしhtmlにするには以下のいずれかです。※ nkfのバージョン2.08以降。
> perl -p -i -e 's/\357\273\277//' BOM.html > perl -p -i -e 's/\xef\xbb\xbf//' BOM.html > sed -i -e 's/\xef\xbb\xbf//' BOM.html # GNU版sed, freebsdの場合 textproc/gsed をインストールする必要あり。 > nkf --in-place -w BOM.html # nkf version 2.08 以降 > nkf --overwrite -w BOM.html # nkf version 2.08 以降
詳細は、`man perlrun`, `man nkf` で