バッチファイルの変数について
はじめましてのかたは、はじめまして。ご存知の方は、そうだよヒズミさんだよ。
今回は、Windowsユーザーならおなじみ?
バッチファイルについて。
アプリの起動ファイルになってたり、定型作業の自動化によく使われるバッチファイルなんですが、
IFとかFORの構文が用意されています。コマンドを羅列するだけものじゃないんですね。
コマンドの結果を受け取る時に、FORは必要になるので、多少なれておく必要はあると思います。
しかし、まず最初に押さえておくべきは、変数の扱いかと思います。
他の言語と違って、癖があるのでその辺を書いていきます。
お品書き
- 変数への代入
- 変数の値の操作
- 遅延環境変数展開
最初に言っておく!
最初に言っておく!
バッチファイルを書くくらいなら、PowerShellスクリプト書いた方が数倍楽です。
あっちも癖があって、けつまづくこともあるけど。
変数への代入
SET hoge = hoge echo %hoge%
ほかの言語では、イコール(=)前後のスペースは有無は関係ないことが多いですね。
しかし、バッチファイルというかコマンドプロンプトの場合は、入れちゃダメっす。
そのスペースも、変数の名前になってしまいます。
つまり、echo %hoge %とすると、値が表示されます。(hogeの後ろに半角スペースが一個入ってます)
ちなみに、変数の値も、”hoge”ではなくて" hoge"と、先頭に半角スペースが入ります。
結果、hoge変数に"hoge"の値を代入したければ、下のように記述します。
REM つまり、こうすれば、おk SET hoge=hoge echo %hoge%
変数の値の操作
バッチファイルの変数は、基本、文字列です。 文字列の連結だけなら、変数を参照して連結したい文字を後ろにくっつけると、後ろに 文字列を連結できる。
SET char=hoge REM echo %char%fuga
変数に入れたものが数字でそれを四則演算したい場合は、SETコマンドの/aを指定する。 指定せずに、他の言語のように演算記号をつけていても、文字列の連結にしかならないので、注意する。
@echo off set num=1+1 set /a num2=1+1 echo %num% echo %num2%
遅延環境変数展開
変数に代入できた。
そして、加算できた?
基本的には、これでおk
でも、一番、ハマりやすいのが、IFやFORの中で変数を使った時です。
例えば、下のバッチスクリプトとかそうのケースです。
@echo off set /a count=0 for /l %%i in (0,1,10) do ( set /a count %count%+1 echo %count% )
よくあるインクリメント(1を加算する)の文ですね。 ほかの言語だと、ループするごとに、変数countの値が一つずつ増えていくと思います。 実際に、実行してみた結果がこちら
C:\Users\endoh\Dropbox\blog\cmd>noIncrement.bat 0 0 0 0 0 0 0 0 0 0 0
え い え ん の ゼ ロ !
なぜ、こんなことになっているのか。
それは、「FOR文は、実行時に一行になる」・「実行前に、変数を展開する」というコマンドプロンプトの挙動のせいです。
@echo onに、書き換えて、実際に流れをみてみます。
C:\Users\endoh\Dropbox\blog\cmd>noIncrement.bat C:\Users\endoh\Dropbox\blog\cmd>set /a count=0 C:\Users\endoh\Dropbox\blog\cmd>for /L %i in (0 1 10) do ( set /a 0+1 echo 0 ) C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0 C:\Users\endoh\Dropbox\blog\cmd>( set /a 0+1 echo 0 ) 0
FOR文の実行前に、COUNT変数の値が展開されてしまうので、
ただ、ひたすら、0+1 の加算とecho 0が繰り返されるだけの悲しい結果に。
結果も格納されないので、countの値は0のままです。
期待通りにインクリメントしてもらうには、「遅延環境変数展開」というものを使います。
やり方は、 setlocalの、パラメータにenabledelayedexpansionを指定します。
@setlocal enabledelayedexpansion @echo off set count=0 for /l %%i in (0,1,10) do ( set /a count=%count%+1 echo %count% )