如何扩展一个CMD shellvariables两次(recursion)

使用Windows XP CMD命令行我可以扩展一个variables两次,如下所示:

set AAA=BBB set BBB=CCC for /F "usebackq tokens=*" %i in (`echo %%AAA%%`) do echo %i 

会回应CCC 。 即AAA已扩展到stringBBB ,然后variablesBBB已扩展到CCC

这从批处理脚本(即.cmd文件)不起作用。 将%%AAA%%更改为%%%AAA%%%%%%%AAA%%%%也不起作用。

任何想法如何我可以从一个脚本内实现这一点,即将可变AAA扩展到stringCCC?

晚编辑

答案张贴工作为我的简单例子,但非曲折的答案不起作用的真实情况。 这是一个扩展的例子(不起作用),它说明了我实际上正在做的事情:

 setlocal enabledelayedexpansion set LIST=BBB CCC DDD set BBB=111 set CCC=222 set DDD=333 for %%i in (%LIST%) do ( for /F %%a in ('echo %%%i%') do echo !%%a! ) 

我想看看

 111 222 333 

输出。

思考一个不太曲折的解决方案,这也产生了你想要的CCC

 setlocal enabledelayedexpansion set AAA=BBB set BBB=CCC for /F %%a in ('echo %AAA%') do echo !%%a! 

编辑:

解剖这个答案:

setlocal enabledelayedexpansion – 这将允许您的蝙蝠中的任何环境变量设置在for循环的过程中被使用。

set AAA=BBBset BBB=CCC – 您的数据填充语句

for /F %%a in ('echo %AAA%') do echo !%%a! – 这告诉处理器循环,尽管只有一次,并从parens中的命令运行中取出返回的第一个标记(空格和制表符的默认分隔符),并将其放入var %% a(outside的一批,一个%将做)。 如果你将var指定为%% a,则需要在do块中使用%% a。 同样,如果您指定%% i,则在do块中使用%% i。 请注意,为了让您的环境变量在for循环的do块中得到解决,您需要将它包围在内! 的。 (你不需要in块中,因为我最初发布 – 我已经在我的编辑做了这个变化)。

编辑:

你和你更新的例子非常接近。 试试像这样:

 @echo off setlocal enabledelayedexpansion set LIST=BBB CCC DDD set BBB=111 set CCC=222 set DDD=333 for %%i in (%LIST%) do ( for /F %%a in ('echo %%i') do echo !%%a! ) 

你的更新和这个不同之处在于你试图in in ('echo %%%i%') in设置环境变量,但没有! 对于设定变量的延迟扩展。 如果你in ('echo !%%i!') ,你会看到你的BBBCCCDDD变量已经解决了,但是你的内部循环的do块没有任何解决方法 – 你没有任何的环境变量。 考虑到这一点,你可以简化你的循环与以下几点:

 @echo off setlocal enabledelayedexpansion set LIST=BBB CCC DDD set BBB=111 set CCC=222 set DDD=333 for %%i in (%LIST%) do (echo !%%i!) 

如何多次展开一个shell变量:

 @echo off setlocal enabledelayedexpansion set myvar=second set second=third set third=fourth set fourth=fifth echo Variable value before expansion: !myvar! call :expand myvar echo Variable value after expansion: !myvar! goto :eof :expand set var=%1 :expand_loop if not "!%var%!" == "" ( set var=!%var%! goto :expand_loop ) set %1=!var! goto :eof 

输出:

 Variable value before expansion: second Variable value after expansion: fifth 

以下(折磨)的方法似乎工作正常:

  @echo off :main setlocal enableextensions enabledelayedexpansion set aaa=bbb set bbb=ccc call :myset x %%aaa%% echo %x% endlocal goto :eof :myset for /F "usebackq tokens=*" %%i in (`echo %%%2%%`) do set %1=%%i goto :eof 

它输出:

 ccc 

如预期的。

我经常使用这个技巧(例如)将%aaa%格式化为%x% ,达到一定的大小(一个sprintf ),但是这是我第一次不得不做双重间接。 这是因为你没有发现额外的"%%"被当前的shell级别所吸引。

这个aaa.bat

 @echo off set aaa=bbb set bbb=ccc for /F %%i in ('echo %%%aaa%%%') do echo %%i 

输出

 c:>ccc 

究竟是什么麻烦?

这是一个有点过时的问题,但有趣的是,答案现在更简单了。 我在Windows 10上运行这些脚本:

 setlocal enabledelayedexpansion set AAA=BBB set BBB=CCC echo !%AAA%! 

输出

 CCC 

对于扩展版本,这可以工作:

 setlocal enabledelayedexpansion set LIST=BBB CCC DDD set BBB=111 set CCC=222 set DDD=333 for %%i in (%LIST%) do ( echo !%%i! ) 

输出

 111 222 333 

双重间接(这是一个非常合适的方式pax已经把它)提醒C指针取消参考。
我怀疑Windows命令外壳是否受支持。

你认为你所瞄准的更大的目标可以通过更简单的方式来实现。
也许更少的代码高尔夫的方法,那么由pax很好地作出的?

看起来最简单的做法是创建一个小的临时文件来设置变量,如你所愿。 像这样的东西应该工作:

 setlocal enabledelayedexpansion set LIST=BBB CCC DDD set BBB=111 set CCC=222 set DDD=333 for %%i in (%LIST%) do ( echo set a=\%%%i\%>tmp.bat call tmp.bat echo %a rm tmp.bat )