Hatena::ブログ(Diary)

IIJIMASの日記 RSSフィード

2010-10-23

バッチファイルで、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が外側にないバッチの中でもコピー&ペーストで使用可能です。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証