以前、setコマンドを用いてバッチファイルで変数を扱う方法を紹介しました。
しかしながら、setコマンドを用いて設定した変数は、広い有効範囲を持ちます。
本記事ではsetコマンドで設定した変数の有効範囲について確認した上で、ローカル変数を扱う「setlocal」と「endlocal」コマンドを紹介します。
まずは関数を用いた場合の挙動について確認してみましょう。以下のようなサンプルバッチファイルについて考えます。
@echo off
set x=2
call :function
echo %x%
pause
:function
set x=3
こちら、functionという名前の関数が定義されており「call :function」でfunction関数が呼び出されます。function関数の実行前にx=2が、function関数内でx=3が代入されています。
この場合「echo %x%」で表示される変数xに入っている値はいくつになるでしょうか。
正解は実行してみるとわかりますが「3」になります。
多くのプログラム言語では、関数内の変数は関数内のみ有効となることが多いため、感覚的に「2」が表示されるのではないかと思う方もいると思いますが、バッチファイルの「set」で定義された変数はグローバル変数的に振舞うため、関数内であろうが値が変更されてしまいます。
別のバッチファイルを用いた場合も、同じような挙動を示します。以下、サンプルバッチファイルです。
@echo off
set x=2
call child.bat
echo %y%
pause
@echo off
echo %x%
set y=3
「parent.bat」から「call child.bat」でchild.batを実行します。child.bat内で変数xを表示し、変数yに3を代入します。その後「parent.bat」の処理に戻って変数yの値を表示します。
この場合のコンソールへの出力結果はどうなるでしょうか。
上記の結果となります。すなわち、parent.bat内で代入されたx=2はchild.bat内でも有効であり、またchild.bat内で代入されたy=3はparent.bat内でも有効です。
2つのバッチファイルに跨っても、変数に代入した値はクリアされることなく残り続けることがわかります。
状況によっては、関数の外と中で同じ名前の変数を使いたいというケースがあると思います。このような状況では、注意しないと意図せずに変数の中身が書き換わってしまうことがあります。
これを防ぐために、バッチファイルでローカル変数を扱うためのコマンド「setlocal」が用意されています。
「setlocal」コマンドと「endlocal」コマンドに挟まれた領域で定義された変数は、この領域の中のみで有効になります。
以下、例を見てみましょう。
最初に紹介した「function.bat」を少しアレンジしたバッチファイルのサンプルが以下となります。「:function」関数の中で、x=3と代入している部分を「setlocal」~「endlocal」で括ってみました。
@echo off
set x=2
call :function
echo %x%
pause
:function
setlocal
set x=3
endlocal
さて、この場合にどのような出力結果となるでしょうか。
上記のように「2」が「echo %x%」で出力されます。すなわち、function関数の中で設定された「x=3」は関数の中のみで有効になっており、関数の処理が終わった後は、最初に代入した「x=2」が有効になっていることがわかります。
このように、「setlocal」コマンドと「endlocal」コマンドに挟まれた領域で定義された変数は、この領域の中のみで有効になります。