29
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

バッチファイルで配列とforeachを使う方法

Last updated at Posted at 2016-05-22

はじめに

Windows バッチファイルには、値の集合を取り扱うためのデータ構造や文法規則はありませんが、シンボル名をうまく処理することで、配列やforeachに近い処理を行うことが出来ます。

要素番号をカウントカウントアップする方法

シンボル名に要素番号を付けて定義することで、疑似的な配列のように扱うことができます。

script.bat
@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コマンドの環境変数一覧を表示する機能を使ってループさせる方法です。
この方法では特定の文字列から始まる環境変数名に対してシーケンシャルに処理を行うことが出来ます。

script.bat
@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に割り当てる。

  1. 変数を二段階に読み込む方法については @plcherrim さんの記事が参考になります。(https://qiita.com/plcherrim/items/c7c477cacf8c97792e17)

29
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?