環境遅延変数の原因と2つのポイント


概要

最近、for文でがっつりはまりました。。。

以下のfor文はファイルの中身を1行ずつ読み取り、
full_nameをechoするもの。この例センスない...
hoge.txtの中身は

read.bat
@echo off
set name=hoge
for /f %%a in (hoge.txt) do (
    set full_name=%%a%name%
    echo %full_name%
)

これを実行すると、以下のような結果となります。

このメッセージ「ECHOはOFFです。」はECHOした変数が初期化されているときに出力されるメッセージです。
つまり、変数full_nameは初期化状態のまま、出力されているということになります。
これが謎でした...

原因

この原因は、変数を読み込むタイミングが問題でした。
%で囲まれた変数はその行の読み始めで展開される
()で囲まれたコマンドは1行とみなされる
のです。まじ謎。
つまり、何度for文を回そうとも、full_nameが初期化状態でechoされていたのです。

環境遅延変数

これを解決するのが、環境遅延変数です。
環境遅延変数とは、変数を読み込むタイミングを遅延させることができる変数で以下のように表します。

  1. 変数を%で囲わず、!で囲む
  2. setlocal enabledelayedexpansionを書く

修正したread.batはこちら

read.bat
@echo off
setlocal enabledelayedexpansion

set name=hoge
for /f %%a in (C:\work\hogehoge\hoge.txt) do (
    set full_name=%%a%name%
    echo !full_name!
)

実行結果は以下のようになり、full_nameが変更されて出力されています。

まとめ

通常、変数を読み込むタイミングは
その行の読み始めで、()で囲まれたコマンドは1行とみなされる

環境遅延変数を用いれば、このタイミングを直前に変更でき、その方法は
1. ()で囲まれたコマンドは1行とみなされる
2. setlocal enabledelayedexpansionを書く