【続】標準入力からの読み取り
7/21標準入力からの読み取りにおいて、set /p コマンドによる標準入力からの読み取りをパイプから行った場合、タイミングが合わないので数行おきにしか読めないと書いた。これを確かめてみた。
1行出力ごとに1秒待つプログラムを作成した。(プログラムはフリーのCコンパイラBorland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borlandで作成。簡単なプログラムなのでソース掲載は省略)これをwaitcopy.exeとする。前回のzz.batと組み合わせて、
dir | waitcopy | zz
結果は、
" ドライブ C のボリューム ラベルは XP です" " ボリューム シリアル番号は 74E4-83F1 です"
と2行表示した後、固まったようになり(*注1*)、数十秒後終わる。おかしい。
普通に dir とやってみると、dir の3行目は空行である。あやしい。
set /p X=
に対して空行を入力してみた。
echo %ERRORLEVEL% 1
駄目だ。zz.bat を再掲するが、
@echo off setlocal :loop set /p X= if not %ERRORLEVEL% == 0 goto :eof echo "%X%" goto loop
つまり、空行ではERRORLEVELが1となるため、EOFと見なされてまい、スクリプトが終わっていたわけだ。
空行とEOFを見分ける手段は無いのか?色々考えて、次のように書き直してみた。
@echo off set X= setlocal :loop set X= set /p X= if not defined X goto :eof echo "%X%" goto loop
set /p の前に一旦、X を未定義化しておき、set /p の後で定義されたかどうかで判断してみた。
でも、結果は同じ。
今日の結論:
(1) タイミングをゆっくりにすれば、パイプからでも読める(*注2*)
(2)空行入力とEOFを区別する手段は無い
なかなか、「明日使えるトリビア」にはならない。トリビアの種募集中。
注1: fputs時にエラーチェックするのをサボったため。エラーチェックするときっとbroken pipeのエラーになるでしょう。
注2: 途中にはさむCプログラムを、「読んだのが空行だったら空白1文字を書く」ように改造し、空行が発生しないようにして問題ないことを確認した。