setlocal~endlocalの外に変数をたくさん持ち出す


setlocal~endlocalの外に変数を持ち出す方法は環境変数PATHを短い名前の形式に変換するでわかりました。こんどはそれをたくさん持ち出す方法を考えます。

課題


なぜそういうことをする必要があるのかが普通は大事なのですけど、プログラミングはそんなことはどうでもよくて、なんとかその課題を解決する方法はないのだろうかと考えることがとても楽しかったりします、、、
set OO_SDK_HOME=C:\Program Files (x86)\LibreOffice 4\sdk
set OFFICE_HOME=C:\Program Files (x86)\LibreOffice 4
set OO_SDK_URE_HOME=C:\Program Files (x86)\LibreOffice 4\URE
やりたいことはこのように変数に代入されたパスを短い名前に変換することです。

変数はもっとたくさんあり、今後その個数は変わるかもしれません。

変数の個数が変わっても修正する箇所が最小限に済むようにしたいです。

環境変数PATHを短い名前の形式に変換すると同じようにしてすぐに出来上がったのが以下。
@echo off
set OO_SDK_HOME=C:\Program Files (x86)\LibreOffice 4\sdk
set OFFICE_HOME=C:\Program Files (x86)\LibreOffice 4
set OO_SDK_URE_HOME=C:\Program Files (x86)\LibreOffice 4\URE
set LF=^


set OO_PATH=OO_SDK_HOME;OFFICE_HOME;OO_SDK_URE_HOME;OO_SDK_MAKE_HOME;OO_SDK_ZIP_HOME;OO_SDK_CPP_HOME;CPP_MANIFEST;CPP_WINDOWS_SDK;OO_SDK_CLI_HOME;OO_SDK_JAVA_HOME;OO_SDK_OUT
set OO_PATH=%OO_PATH:;=!LF!%
setlocal enabledelayedexpansion
  for /f "delims=" %%i in ("%OO_PATH%") do (
    for %%j in ("!%%i!") do set %%i=%%~fdsj
  )
  echo %OO_SDK_HOME%
  echo %OFFICE_HOME%
  echo %OO_SDK_URE_HOME%
  echo endlocalの前
  echo.
endlocal
echo endlocalの後
echo %OO_SDK_HOME%
echo %OFFICE_HOME%
echo %OO_SDK_URE_HOME%
echo.
pause
8行目にいまのところ変換したい変数名をセミコロン;で区切って列挙してOO_PATHに代入しています。

今後変数が増減してもこの部分さえ変更すれば対応できるようにしたいです。

変数は全部で11個ありますが面倒なので上のコードでは3つにしか値を代入していません。

このバッチファイルを実行してみます。

C:\PROGRA~2\LIBREO~1\sdk
C:\PROGRA~2\LIBREO~1
C:\PROGRA~2\LIBREO~1\URE
endlocalの前

endlocalの後
C:\Program Files (x86)\LibreOffice 4\sdk
C:\Program Files (x86)\LibreOffice 4
C:\Program Files (x86)\LibreOffice 4\URE

続行するには何かキーを押してください . . .

endlocalの後ではsetlocal~endlocalでやった処理が反映されていませんね。

setlocal~endlocalの中のたくさんの変数を持ち出す方法

endlocal & set OO_SDK_HOME=%OO_SDK_HOME% & set OFFICE_HOME=%OFFICE_HOME% & set OO_SDK_URE_HOME=%OO_SDK_URE_HOME%
変数が3つだけなら19行目をこのようにすれば解決です。

でも変数が11個となり、さらに個数も不定となるとこのような対応はしていられません。

そこで悩んでたどり着いたのがbatch file - Make an environment variable survive ENDLOCAL - Stack OverflowのQ&A。

ここに書いてあることはよく理解できなかったのですが、どうやらfor文を使えば変数をたくさんもちだせることはわかりました。

(H26.2.14追記「&」 - DOS コマンド一覧を読んで理屈がわかりました。endlocalのある行では%変数%に!変数!が入ります。そこでfor ~ in ( ~ ) do ( ~ ) が一行と解釈されることを利用してこれをendlocalと同じ行に解釈させているということのようです。)
@echo off
set OO_SDK_HOME=C:\Program Files (x86)\LibreOffice 4\sdk
set OFFICE_HOME=C:\Program Files (x86)\LibreOffice 4
set OO_SDK_URE_HOME=C:\Program Files (x86)\LibreOffice 4\URE
set LF=^


set OO_PATH=OO_SDK_HOME;OFFICE_HOME;OO_SDK_URE_HOME;OO_SDK_MAKE_HOME;OO_SDK_ZIP_HOME;OO_SDK_CPP_HOME;CPP_MANIFEST;CPP_WINDOWS_SDK;OO_SDK_CLI_HOME;OO_SDK_JAVA_HOME;OO_SDK_OUT
set OO_PATH=%OO_PATH:;=!LF!%
setlocal enabledelayedexpansion
  for /f "delims=" %%i in ("%OO_PATH%") do (
    for %%j in ("!%%i!") do set OO_PATH1=!OO_PATH1!%%i,%%~fdsj;
  )
  set OO_PATH1=%OO_PATH1:~0,-1%
endlocal & set OO_PATH=%OO_PATH1%
set OO_PATH=%OO_PATH:;=!LF!%
setlocal enabledelayedexpansion
  for /f "tokens=1,2 delims=," %%i in ("%OO_PATH%") do endlocal & set %%i=%%j
echo endlocalの後
echo %OO_SDK_HOME%
echo %OFFICE_HOME%
echo %OO_SDK_URE_HOME%
echo.
pause
これでうまくいきました。

12行目で変数名と短い名前に変換したパスをカンマ,で対応させて、セミコロン;で繋げてOO_PATH1に代入します。

15行目で一旦OO_PATH1をsetlocal~endlocalの外に出します。

16行目でOO_PATH1のセミコロン;を文字列!LF!に置換します。

 置換後のOO_PATH1の値は、変数名,変数の値!LF!変数名,変数の値!LF!変数名,変数の値!LF!、のようになっています。

5行目で変数LFには改行コードを代入してあるので、17行目でsetlocal enabledelayedexpansion~endlocalの中に入ると!LF!は改行コードに変換されます。
  for /f "tokens=1,2 delims=," %%i in ("%OO_PATH%") do endlocal & set %%i=%%j
この18行目でOO_PATH1の各行の、変数名,短い名前に変換したパス、のセットを"tokens=1,2 delims=,"で1番目のtoken変数名を%%i、2番目のtokenパスを%%jで受け取りdoのあとでsetしています。

参考にしたサイト


batch file - Make an environment variable survive ENDLOCAL - Stack Overflow
このQ&Aをヒントにしました。

「&」 - DOS コマンド一覧
endlocalのある行では%変数%に!変数!が入ることを利用してendlocalの外に変数を出します。
PR

0 件のコメント:

コメントを投稿