バッチファイルで、setlocal〜endlocal内での変数の値を外部に引き継ぎたい!
setlocal/endlocalコマンドは環境変数のローカル化のためにあります。
ローカル化とはsetlocalからendlocalの範囲内で定義した変数がその中だけ有効でその外部の同名の変数に影響を及ぼさないようにすることです。
@echo off setlocal set a=1 echo %a% endlocal echo %a% goto :EOF
を実行すると
1 ECHO は <OFF> です。
となります。
入れ子にもできます。
@echo off setlocal set a=0 setlocal echo %a% set a=1 setlocal echo %a% set a=2 echo %a% endlocal echo %a% endlocal echo %a% endlocal goto :EOF
を実行すると
0 1 2 1 0
となります。外側から内側へは同名の変数の値が保存されますが、endlocalのあとは同一階層でsetした値が復元されてしまいます。
setlocalにはenabledelayedexpansion(遅延環境変数の展開)という有用なオプションがあります。しかし、それを使うサブルーチンはsetlocal-endlocalの内側になってしまいます。遅延環境変数の展開の機能を使って何かを求めたのに、endlocalで消えてしまうのはもったいないです。
そもそも、これらのコマンドは「外側をに影響をさせない」ためにあるのですが、内側から外側に値を渡したいことがしばしばあります。どうすればいいのでしょう?
実は、以下のようにすると…
@echo off setlocal set a=0 setlocal echo %a% set a=1 setlocal echo %a% set a=2 echo %a% endlocal && set a=%a% echo %a% endlocal && set a=%a% echo %a% endlocal && set a=%a% goto :EOF
これを実行すると
0 1 2 2 2
となりendlocalの外に値が引き継げました!
これを用いて、以前書いたエントリの文字列の部分文字列を取得するサブルーチンをどこでもそれを持っていけるように書き直してみます。
::部分文字列取得 部分文字列を取得する ::使用法 call :GET_SUBSTR (文字列) (開始インデックス) (部分文字列の長さ) :: そのあとで、substrの中に格納 :GET_SUBSTR setlocal enabledelayedexpansion set str=%1 set startIndex=%2 set length=%3 ::setlocalでenabledelayedexpansionを宣言しているので以下の記述が可能。 set substr=!str:~%startIndex%,%length%! endlocal && set substr=%substr% exit /b
これなら、enabledelayedexpansionつきのsetlocalが外側にないバッチの中でもコピー&ペーストで使用可能です。