【続】環境変数に改行文字をセット

前回からの続き。

set X=echo 1^

echo 2

という風に環境変数AAにセットした2行の命令をそれぞれ実行するにはどうするか。前回書いたように、

%X%
!X!

とも駄目である。
iffor( )構文解析% による環境変数置換に先立って行われることを思い出して、

(%X%)
(!X!)

とやってみると前者で希望通りの動きをする。後者は !X! と同様1命令と扱われる。

横道にそれてしまったが、環境変数に複数の命令をセットして実行したいなら、別に改行をはさまなくても、

set Y=echo 1 ^& echo 2

と言う風に、&^エスケープして環境変数にセットすれば、

%Y%

で実行できる。このときも、

!Y!

だと、1命令と扱われ、1 & echo 2 が表示される。

本題に戻って、改行文字の使い道を考える。
環境変数に複数行を記録するときの1つのやり方は、tail コマンドでやったように環境変数名に連番をつけて複数の変数に1行ずつ記録するやり方がある。tail コマンドは記憶する内容が順次変動するのでそのやり方しかないが、そうでなければ1つの環境変数に改行文字を挟みながら記録するというのも考えられる。サンプルとしては以下のよう。複数行をセットした後、改行を @ に置換してみた。

@echo off
setlocal enabledelayedexpansion
set AA=
for /f "delims=" %%I in ('DIR') do (
  set AA=!AA!^

%%I
)
set AA1=!AA:^

=@!
set AA 

なお、今回いろいろ試していた時に発見したのだが、

setlocal enabledelayedexpansion
set AA=echo 123
%AA%           ⇒  これは期待通り 123 が表示される
!AA!           ⇒  これは期待通り 123 が表示される
(!AA!)          ⇒  これは期待通り 123 が表示される
%AA% | more    ⇒  これは期待通り 123 が表示される
!AA! | more    ⇒  これは 'echo 123' がコマンド名と見なされエラー
(!AA!) | more   ⇒  これは '!AA!' がコマンド名と見なされエラー

である。ちょっと不思議だが、この謎は解けるか?