はじめに
Windows バッチファイルには、値の集合を取り扱うためのデータ構造や文法規則はありませんが、シンボル名をうまく処理することで、配列やforeachに近い処理を行うことが出来ます。
要素番号をカウントカウントアップする方法
シンボル名に要素番号を付けて定義することで、疑似的な配列のように扱うことができます。
@echo off
setlocal enabledelayedexpansion
rem 要素番号をつけて変数を定義
set month_1=January
set month_2=February
set month_3=March
rem foreachループ
set i=1
:FOREACH_MONTH
set it=!month_%i%!
if defined it (
echo month_%i%=%it%
set /a i+=1
goto :FOREACH_MONTH
)
実行結果
変数month_<n>
を数値順に表示して、スクリプトは終了します。
>call script.bat
month_1=January
month_2=February
month_3=March
解説
エコー機能の無効化と遅延環境変数機能の有効化を実施します。
遅延環境変数は、後述するイテレータ(it
)へのset
において必要となる機能です。
@echo off
setlocal enabledelayedexpansion
配列を模擬して添え字を付けた変数month_<n>
を設定します。
set month_1=January
set month_2=February
set month_3=March
ループでは、添え字(i
)を用いてmonth_<n>
の要素を取り出してイテレータ(it
)へ代入します。
これは遅延環境変数によって、下記の通り二段階の変数読み込みを実行して実現されます。1
set it=!month_%i%!
=!month_1! # 行解釈時に環境変数(%)を読み込み
=January # コマンド実行時に遅延環境変数(!)を読み込み
it
への代入が有効な場合、if defined
の条件が満たされて、カウンターのインクリメントと、ループ先頭へのジャンプが実行されます。
if defined it (
echo month_%i%=%it%
set /a i+=1
goto :FOREACH_MONTH
)
ループ回数が進み、存在しない添え字付き変数にたどり着くと、set it=
によってit
が削除されます。
これによりif defined it
の条件が不成立となるため、ループが終了します。
setの変数一覧を使う方法
set
コマンドの環境変数一覧を表示する機能を使ってループさせる方法です。
この方法では特定の文字列から始まる環境変数名に対してシーケンシャルに処理を行うことが出来ます。
@echo off
rem monthから始まる環境変数
set month_1=January
set month_2=February
set month_12=December
set monthly=True
for /f "usebackq delims== tokens=1,2" %%a in (`set month`) do (
echo %%a, %%b
)
実行結果
month
から始まる変数を文字列順に表示して終了します。
>call script.bat
monthly, True
month_1, January
month_12, December
month_2, February
解説
この方法ではfor
コマンドのトークンスイッチ/f
を使ってset month
コマンドの実行結果を順次処理しています。
FOR /F ["オプション"] %変数 IN (`コマンド`) DO コマンド [コマンド パラメーター]
set month
コマンドを実行すると、month
から始まる環境変数一覧を文字列順に出力します。
>set month
monthly=True
month_1=January
month_12=December
month_2=February
オプションの意味はそれぞれ下記のとおりです。
usebackq
: 逆引用符で囲まれた文字列をコマンドとして処理して、結果を1行ずつ読み込む。
delims==
: 区切り文字を=
にしてトークンに分解する。
tokens=1,2
: 分解されたトークンのうち1番目を%%a
、2番目を%%b
に割り当てる。
-
変数を二段階に読み込む方法については @plcherrim さんの記事が参考になります。(https://qiita.com/plcherrim/items/c7c477cacf8c97792e17) ↩