如何两次扩展CMD shell变量(递归)

时间:2009-07-29 12:33:54

标签: windows shell scripting batch-file cmd

使用Windows XP CMD命令行,我可以将变量扩展两次,如下所示:

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

将回显CCC。即AAA已扩展为字符串BBB,然后变量BBB已扩展为CCC

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

知道如何从脚本中实现这一点,即将变量AAA扩展为字符串CCC?

延迟修改

这些答案发布了我的缩减示例,但非曲折的答案对真实案例不起作用。这是一个扩展示例(不起作用),它说明了我实际上要做的事情:

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

输出

7 个答案:

答案 0 :(得分:13)

从一个不那么曲折的解决方案的角度思考,这也会产生你想要的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 - 您的数据填充set语句

for /F %%a in ('echo %AAA%') do echo !%%a! - 这告诉处理器循环,虽然只循环一次,并从parens中的命令运行中取出返回的第一个标记(空格的默认分隔符和tab应用)并将其放入在var %% a中(在批处理之外,单个%会这样做)。如果将var指定为%% a,则需要在do块中使用%% a。同样,如果您指定%% i,请在do块中使用%% i。请注意,要使您的环境变量在do循环的for块中得到解析,您需要将其包围在!中。 (你不需要在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 ('echo !%%i!'),您会看到已解析BBBCCCDDD个变量,但内循环的do块不会要解决的任何事情 - 你没有任何111环境变量。考虑到这一点,您可以使用以下内容简化循环:

@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!)

答案 1 :(得分:8)

如何多次展开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

答案 2 :(得分:3)

以下(曲折)方法似乎没有问题:

    @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%到一定的大小(la sprintf)但这是我第一次拥有做双重间接。它的工作原理是因为您没有找到当前shell级别所吸引的额外"%%"

答案 3 :(得分:3)

这是aaa.bat

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

输出

c:>ccc

究竟是什么问题?

答案 4 :(得分:1)

OP问题几乎适用于Windows 10.需要进行小的修正才能正确形成ECHO命令。这是中间结果:

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

rem // Outputs:
rem // %AAA%
rem // %BBB%
rem // %CCC%

然后我们将输出嵌套在另一个FOR语句中并获得完整的结果:

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

rem // Outputs:
rem // 111
rem // 222
rem // 333

答案 5 :(得分:0)

双重间接(这是一种非常恰当的方式pax已经把它)提醒C指针解除引用。
我怀疑Windows command shell是否支持。

您是否认为您所针对的更大目标可以通过更简单的方式实现;
也许较少的代码 - 高尔夫方法然后pax很好地设计了一个?

答案 6 :(得分:0)

似乎最简单的事情就是创建一个微小的临时文件来根据需要设置变量。这样的事情应该有效:

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
)