小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

DOSバッチファイルでのfor文とcall文等について

複数のファイルをcopyコマンドで一つに連結し、sortコマンドでソートした後、重複行を削除したいと思い、 UNIXでのuniqコマンドに相当するものがWINDOWSでもないかと探してみました。

ちなみに、uniqコマンドとは、重複行を単一行のユニーク(uniq)にするコマンドです。


http://www.fpcu.jp/dosvcmd/bbs/log/unixdoswindows/3-0062.html


そこにDOSバッチファイルでのuniqコマンドもどき(uniq.bat)のソースがありました。しかし、たった14行のソースなのですが全く読めません(わかりません)。そこで、調べてみました。以下はそのメモです。

uniq.batのソースの引用

  1. echo off
  2. set prev=
  3. if not exist "%1" goto error
  4. for /f "tokens=* delims=" %%L in ( %1 ) do call :sub %%L
  5. goto exit
  6. :sub
  7. if not "%prev%"=="%*" set prev=%*&&echo %*
  8. goto :EOF
  9. :error
  10. echo.
  11. echo 表示したいファイル名を指定してください。
  12. echo [例] uniq.bat file.txt
  13. echo.
  14. :exit

ソース説明

1の『echo off』

エコーオフです(そのまんま)。ちなみに、エコーオンでコマンドを実行すると、コマンド実行文そのものやその実行結果が、すべてコマンドプロンプトに出力される。エコーコマンドのみのエコー出力をしたい場合は、『echo off』にします。また、『echo off』自体もオフにしたい場合は『@echo off』とします。

2の『set prev=』

環境変数の設定です。重複を求めるために読み込んだ一行分データを格納する変数です(この段階ではなにも設定していない)。

3の『if not exist "%1" goto error

起動時の第一引数(%1)が存在しない時は、『goto error』しています。

4の『for /f "tokens=* delims=" %%L in ( %1 ) do call :sub %%L』

第一引数(%1)で指定されたファイルから一行読み込んで変数『%%L』にセットし、別プロセス(call)でサブルーチン『sub』を、引数に『%%L』の値をセットして呼んでいます。これを、ファイルのすべての行に対して繰り返『for』します。
for文に関して詳しい説明は、以下を参照願います。


http://forum.nifty.com/fpcu/dosvcmd/batch.htm#for


補足:『sub』は同ソース上にありますが、『call』で呼ばれたときには、呼び側プロセスと別プロセスになり、『goto :EOF』を実行後、呼び側プロセスに戻ってきます。また、『%%L』は、バッチファイル内では%%Lですが、コマンドプロンプトに直接入力の時は%Lとなります。

5の『goto exit』

『goto exit』して処理を終了しています。

6の『:sub』

サブルーチンです。別プロセスになります。

7の『if not "%prev%"=="%*" set prev=%*&&echo %*』

環境変数prevとサブルーチン全引数をまとめたもの(%*)、つまり、一行読みデータが等しくないかを判断し、もしそうなら、環境変数prevに一行読みデータ(サブルーチン全引数のまとめもの(%*))を設定しなおして、そのコマンドが成功したら(&&)、一行読みデータ(%*)をエコーする。

補足:&&は、直前のコマンドが成功したら&&以降を実行すること。また、%1〜%9は、引数の個数分に対応しており、%*は、それをすべてまとめたもの。

8の『goto :EOF』

WindowsNT/2000/XPでは、あらかじめ暗黙に定義された「ファイル末尾」を意味するラベル 『:EOF』 が利用できる。

9から14

割愛、ちなにみ『echo.』は、空行出力とのことです。


参考 : http://forum.nifty.com/fpcu/dosvcmd/batch.htm

uniq.bat使用例

C:\Documents and Settings\xxx>type test.txt
123456789
111111111
111111111
111111111
222222222
C:\Documents and Settings\xxx>uniq test.txt

C:\Documents and Settings\xxx>echo off
123456789
111111111
222222222

uniqコマンドを実行したことにより、111111111の行がユニークになりました。