バッチファイル界の魔境『遅延環境変数』に挑む（おまけもあるよ）

　今回は、**for**と双璧を為すバッチファイル界の魔境、**遅延環境変数**に挑みたいと思います。

#１．遅延環境変数とは？
　さて、大分前に投稿した[.bat（バッチファイル）のforコマンド解説。](http://qiita.com/sawa_tsuka/items/67be34bab1fdf3fb87f9)の中で、次のようなことを述べました。（見なくても問題ないです）
> 　特に遅延環境変数については、for文を使う上でほぼ確実に理解する必要が出てくると思われます。

　その理由を説明するには、バッチファイルでの「変数を読み込むタイミング」について知っておく必要があります。

##変数の読み込みタイミング
　次のコードをご覧下さい。

```bat:例1.bat
@set num=1
@if %num% == 1 (
	set /a num+=1
	echo %num%
)
@pause
```
　ちなみに、このページ内にあるコード表示は、そのままコピー＆ペーストでバッチファイルとして動くようになっています。 *実行しても、ええんやで。*

　さて、話を戻して…。上のコード、実行結果はどうなると思いますか？
　まず最初はnumが１なので、if文は真になりますね。ここまでは特に大したことはありませんが…。
　if文の最初で、numに１を加算しています。つまり、**numの値は２になっているはずです。**次の行で出力しているので２と表示されるはずなのですが…？

　このコード、**出力結果は１になります。**

　この現象こそが、変数を読み込むタイミングが顕著に影響を及ぼす例です。
　通常変数は％記号で囲みますが、この％で囲った変数は、**その変数がある行に『入った瞬間』にすべて展開されます。**

　そして、**カッコで囲った複数のコマンドは、その行数に関わらず、１行とみなして変数が展開されます。**

　つまりこのコード、if文に入った瞬間に変数が全て展開されてしまうので、echo時に加算が反映されていないのです。

　加算自体は行われていますので、カッコを抜けた後に再度echoしなおせば、きちんと２と表示されます。

***
　というわけで、変数の読み込みタイミングは**行に入った瞬間である**こと、**カッコは１まとまりと認識されること**が分かりました。

　では、遅延環境変数とは何か？についての答えを出したいと思います。

　**遅延環境変数とは、変数を読み込むタイミングを遅らせる変数である！**

#２．遅延環境変数とは？
　遅延環境変数を使うには、変数を囲む％記号を！記号に変えるだけ。
　こうすると、その変数を読み込むタイミングが、『行に入った瞬間』から『その変数を使うコマンドにたどり着いた瞬間』になります。

　試しに、先ほどのコードのecho行を遅延環境変数に変えてみましょう。

```bat:例1.bat
@setlocal enabledelayedexpansion
@set num=1
@if %num% == 1 (
	set /a num+=1
	echo !num!
)
@pause
```
　これで、きちんと２がechoされます。ですが、変な行が増えていますね？

　```setlocal enabledelayedexpansion```と書かないと、遅延環境変数が使えませんので、使う場合は何も考えずに文頭に書いてください。

#３．いつ使う？～①かっこ内で～
　遅延環境変数は、基本的にかっこの中で使うことが多いです。その理由は先述した通りですが、ではかっこを使うのってどんな時でしょうか。

　それは、**if**文と**for**文です。もちろんほかのコマンドで使うこともありますが、群を抜いて最多はこの２つでしょう。それぞれどんな使い方をするのかについては、別に解説ページを設けていますので作者マイページからご覧いただければ幸いです。

#４．いつ使う？～②変数を二重に読み込む～
　突然ですが。あなたはバッチファイルで数列の項を計算しています。n項めの数字を、number[n]という名前の変数にそれぞれ保存しました。

　さて、計算が終わり、いざまとめて出力する段になりました。forは難しいので、ラベルを使ってn回のループを行い、数列の各項の数字を出力したいです。

　……といった場合。
　変数の名前は```number[%n%]```ですので、表示しようとしたら```echo %number[%n%]%```…？

　これでは動きませんね。なぜなら、```%number[%n%]%```という変数は、```%number[%```と```%]%```という分割のされ方をしてしまうためです。ではどうすればいいか？

　```!number[%n%]!```としてみましょう。さながら数式の小かっこと中かっこのような役割を果たします。**行に入った瞬間に%%**、**コマンドに入った瞬間に!!**が読み込まれるわけですね。

##４－おまけ．変数を2重に読み込むその他の方法（2016/5/29追記）
　実は変数を2重に読み込む方法というのはほかにも存在します。それらをご紹介します。

###方法１．call set～2回解釈させる～
　```echo %number[%n%]%```では動かないという話をしました。遅延を使わずに二重展開するにはどうすればよいでしょうか？
　答えは、**echo文を2回解釈させる**です。具体的には、```call echo %%number[%n%]%%```としましょう。

　```call```は、以降のコマンドを実行する、という効果を持ちます。（それ以外もたくさんありますが。）
　そしてコマンドを読み込むと、```%```は変数のしるしとして、```%%```は**%ひとつ**として解釈されます。つまり、```call echo %%number[%n%]%%```は```echo %number[ｎの中身]%```を実行しろ、という指示になり正常に実行できるというわけですね。

　ちなみに、!!としても同様の効果を得ることはできません。できるのは%%だけですので気を付けましょう。

　また、この使い方をすると、外側の変数（ここでは%num[ｎの中身]%のほう）は遅延読み込み扱いになります。callが終わった後にechoコマンドに辿り着くので、**『その変数を使うコマンドにたどり着いた瞬間』**という遅延の条件を強制的に満たさせるわけですね。
　ちなみに、内側（ここでは%n%のほう）は、↑の条件を満たさないため自動で遅延にはなりません。カッコ内でcallを用いた2重読み込みをしたい場合は、```call echo %%number[!n!]%%```とするとうまくいきます。曲芸みたいなことをしていますが、考えながら読めば理解は難しくないと思います。

###方法２．set /a～計算式中の変数は常に遅延展開される～
　もうひとつ、**変数の中身が数字の場合に限り**可能な方法を挙げます。
それは、```set /a a=number[%n%]```とすることです。余分に変数が一つ必要になりますが、これで変数aの中に二重に展開された数が代入されます。数字を代入したい場合（カッコの中などで結構多いです）はこちらのほうがスマートだと思います。

　どういう原理かというと、まず```set /a```中では変数を%や!でくくる必要がありません。**式中の変数は、すべてset /aコマンド開始時に自動で読み込まれます。**
　コマンド開始時に……ということは、遅延展開ということですね。文中の%%は行に入った瞬間、!!もset /aより先に読み込まれますので、『くくった変数が読み込まれる→くくってない変数が遅延で読み込まれる』という流れを達成したことになります。!!も先に読み込んでくれますので、カッコ中では```set /a a=number[!n!]```として問題ありません。

#５．まとめ
　遅延環境変数は、①かっこ内で変数を使うとき、②変数を2重に読み込むときに使用します。とはいえ最初のうちは慣れないことと思いますので、様々なところでこまめにechoして挙動を理解しましょう。

　最後まで読んでいただき、有難うございました。
　誤り・感想・要望などありましたら、是非コメントにお願いいたします。