Logo address

EOL-EOF 問題

目次

EOL-EOF 問題

ここで言う EOL(end of line)-EOF(end of file) 問題と言うのは、テキストファイルの最後が EOL で終わるのか、終わらなくても良いのかと言う問題である。
unix の初期のエディタはラインエディタであったため、テキストファイルは自動的に EOL で終わった。unix ではそのような事情もあって、unix 由来のツールは EOL で終わる事を想定している。
emacs が登場すると話がややこしくなった。編集は文字を単位としているために、EOL で終了しないテキストを(原理的には)作る事が可能で、僕の記憶によると、初期の emacs はそうだったと思う。(間違っていたらゴメン)
現在の emacs は、テキストをファイルを保存する時に、テキストが EOL で終わっていない場合には EOL を強制的に末尾に付ける。emacs のマニュアルを見ても EOL を付けるか否かの起動オプションが見当たらないので、EOL で終わるのが正しいテキストファイルであると考えているのだろう。

OSX のテキストエディタ

Mac/OSX のテキストエディタ(TextEdit.app) の場合には EOL で終わらないテキストファイルを作成できる。フリーのテキストエディタ mi もそうである。従って OSX ではテキストファイルをアプリケーションが読み取る時に、この問題に注意しないとバグることになる。(大抵のプログラムの教科書に書かれている、1行づつテキストを読み取って処理するプログラムは endless loop にハマる)
またファイルの最後に1行を追加するのに

	echo '.....'  >>  foo
のような書き方もバグる。

1行の追加問題

さて僕が古典的な問題を採り上げたのは、僕がこの年の秋学期からの ubuntu を使った実習環境を整備する時に、あるファイル(foo とせよ)の最後に一行を追加する必要があった。そのファイル(foo)の末尾が EOL で終わっている事の確信がない。台数が多いので、環境の設定はシェルスクリプトを使う事になる。そこで foo の末尾が EOL で終わっていない場合に、まず

	echo >> foo
によって EOL を末尾に付加した後に
	cat bar >> foo
のような処理を行う必要がある。bar は追加する1行だけからなるファイルである。

EOL 判定

foo の末尾が EOL で終わっているか、いないかをどのように判定したらよいだろうか? これはちょっとしたパズルである。いろいろ考えたあげくに、僕が採用したのは

	a1=`wc -l < foo`
	a2=`grep '^' < foo | wc -l`
	if [ $a1 != $a2 ];
	then
		echo >> foo
	fi
	cat bar >> foo
である。(多分、これでうまくいくでしょう)

ubuntu の gedit

ubuntu の gedit は機械的に EOL を追加している。テキストの末尾が既に EOL で終わっていてもだ!
従って由緒正しくテキストを作ると、ファイルの末尾に EOL が2つも付く!