head コマンドが作れるか? (2)
昨日の続き。
for 文の中で行数をカウントできないとすると外でやるしかない。一旦外に出て帰ってくるわけだ。このとき、外でも for 制御変数が有効かどうかを調べてみる。
rem スクリプト1: for /f "delims=" %%A in (test.txt) do call :sub goto :eof :sub echo %%A
rem スクリプト2: for /f "delims=" %%A in (test.txt) do ( goto :sub :ret ) goto :eof :sub echo %%A goto :ret
まずスクリプト1だが、「%A」が行数分表示されるだけである。つまり for 制御変数は for 文の外では有効でない。スクリプト2に至っては「) の使い方が誤っています。」という構文エラーとなる。 :ret と ) の間に rem の行を入れるとエラーは出なくなるが、「%A」が1つ表示されただけで終わってしまう。for 文から goto で飛び出すとその段階で for 文が終結してしまうようだ。
いずれにせよ、だめである。そこで、表示だけ中でやって行数カウントを外でやることを考える。
goto で外へ行くのは駄目なことはわかったので、call で外のサブルーチンを呼ぶことにする。
rem スクリプト3: setlocal set N=0 for /f "delims=" %%A in (test.txt) do ( call :sub echo %%A ) goto :eof :sub set /a N=N+1 if %N% geq 20 exit /b
exit /? によると、exit /b は「現在のバッチ スクリプトを終了する」と書いてあるので使ってみた。しかし、20行でなく全行表示されてしまう。サブルーチンの中で使った場合は、バッチスクリプトの終了でなく、サブルーチンの終了になってしまうようだ。ということは、goto :eof と等価である。意味ねー。
goto で飛び出れば for が終了するのでいいのでは? と、次のようにしてみる。
rem スクリプト4: setlocal set N=0 for /f "delims=" %%A in (test.txt) do ( call :sub echo %%A ) :out goto :eof :sub set /a N=N+1 if %N% geq 20 goto out
が、駄目である。さっきと同じく全行が表示される。サブルーチンから飛び出ても for から飛び出たと判断してもらえないようだ。
つづく