windows 如何将 CMD shell 变量扩展两次(递归)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1199931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to expand a CMD shell variable twice (recursively)
提问by jon-hanson
Using the Windows XP CMD command-line I can expand a variable twice as follows:
使用 Windows XP CMD 命令行,我可以将变量扩展两次,如下所示:
set AAA=BBB
set BBB=CCC
for /F "usebackq tokens=*" %i in (`echo %%AAA%%`) do echo %i
will echo CCC
. I.e. AAA
has been expanded to the string BBB
, and then the variable BBB
has been expanded to CCC
.
会回声CCC
。即AAA
已经扩大到字符串BBB
,然后变量BBB
已经扩大到CCC
。
This doesn't work from inside a batch script (i.e. a .cmd file). Changing the %%AAA%%
to either %%%AAA%%%
or %%%%AAA%%%%
doesn't work either.
这在批处理脚本(即 .cmd 文件)中不起作用。将 更改%%AAA%%
为%%%AAA%%%
或%%%%AAA%%%%
也不起作用。
Any idea how i can achieve this from within a script, namely to take expand the variable AAA to the string CCC?
知道如何从脚本中实现这一点,即将变量 AAA 扩展为字符串 CCC?
Late Edit
后期编辑
The answers posted work for my reduced example however the non-tortuous answer doesn't work for the real case. Here's an extended example (which doesn't work), which illustrates what I was actually trying to do:
答案发布适用于我的简化示例,但非曲折的答案不适用于真实案例。这是一个扩展示例(不起作用),它说明了我实际尝试做的事情:
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!
)
I would like to see
我想看看
111
222
333
output.
输出。
回答by akf
Thinking in terms of a less tortuous solution, this, too, produces the CCC
you desire.
考虑一个不太曲折的解决方案,这也产生了CCC
你想要的。
setlocal enabledelayedexpansion
set AAA=BBB
set BBB=CCC
for /F %%a in ('echo %AAA%') do echo !%%a!
edit:
编辑:
to dissect this answer:
剖析这个答案:
setlocal enabledelayedexpansion
- this will allow for any environment variable setting during your bat to be used as modified during the process of your for
loop.
setlocal enabledelayedexpansion
- 这将允许在您的 bat 期间使用任何环境变量设置,以便在您的for
循环过程中进行修改。
set AAA=BBB
, set BBB=CCC
- your data population set
statements
set AAA=BBB
, set BBB=CCC
- 您的数据填充set
语句
for /F %%a in ('echo %AAA%') do echo !%%a!
- This tells the processor to loop, albeit only once, and take out the first token that is returned (default delimiter of space and tab apply) from the running of the command in the parens and put it in the var %%a (outside of a batch, a single % will do). If you specify that var as %%a, you need to use %%a in your do
block. Likewise, if you specify %%i, use %%i in your do
block. Note that to get your environment variable to be resolved within the do
block of the for
loop, you need surround it in !
's. (you don't need to in the in
block, as I originally posted - I have made that change in my edit).
for /F %%a in ('echo %AAA%') do echo !%%a!
- 这告诉处理器循环,尽管只循环一次,并从括号中的命令运行中取出返回的第一个标记(空格和制表符的默认分隔符应用)并将其放入 var %%a(外部一个批次,一个 % 就可以了)。如果将该 var 指定为 %%a,则需要在do
块中使用 %%a 。同样,如果您指定 %%i,请在do
块中使用 %%i 。请注意,要do
在for
循环块内解析您的环境变量,您需要将其括在!
's 中。(您不需要在in
块中,正如我最初发布的那样 - 我已经在我的编辑中进行了更改)。
edit:
编辑:
You were very close with your updated example. Try it like this:
您与更新的示例非常接近。像这样尝试:
@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!
)
The difference between your update and this is that you were trying to echo the environment variable in the in
set with in ('echo %%%i%')
, but without the !
's for the delayed expansion of set variables. Were you to use in ('echo !%%i!')
, you would see your BBB
, CCC
, and DDD
variables resolved, but then the do
block of your inner loop wouldnt have anything to resolve - you dont have any 111
environment variables. With that in mind, you could simplify your loop with the following:
您的更新与此之间的区别在于您试图用 回显in
集合中的环境变量in ('echo %%%i%')
,但没有!
用于延迟扩展设置变量的's。如果您使用in ('echo !%%i!')
,您会看到您的BBB
、CCC
和DDD
变量已解析,但是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!)
回答by Piotr Dobrogost
How to expand a shell variable multiple times:
如何多次扩展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
output:
输出:
Variable value before expansion: second
Variable value after expansion: fifth
回答by paxdiablo
The following (torturous) approach seems to work okay:
以下(折磨)方法似乎可以正常工作:
@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
It outputs:
它输出:
ccc
as desired.
如预期的。
I've often used that trick to (for example) format %aaa%
into %x%
to a certain size (a la sprintf
) but this is the first time I've had to do double indirection. It works because you don't find the extra "%%"
being sucked up by the current shell level.
我经常使用这个技巧来(例如)格式化%aaa%
为%x%
特定大小(a la sprintf
),但这是我第一次不得不进行双重间接访问。它之所以有效,是因为您没有发现"%%"
当前 shell 级别吸收了额外的内容。
回答by wqw
This aaa.bat
这个aaa.bat
@echo off
set aaa=bbb
set bbb=ccc
for /F %%i in ('echo %%%aaa%%%') do echo %%i
outputs
输出
c:>ccc
What exactly is the trouble?
究竟是什么问题?
回答by Stephen Quan
The OP question almost works on Windows 10. A small correction is required to properly form the ECHO
command. Here is the intermediate result:
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%
Then we nest the output inside another FOR
statement and get the completed result:
然后我们将输出嵌套在另一个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
回答by james turner
it seems like the easiest thing to do is to create a tiny temp file to set the variable as you wish. something like this should work:
似乎最简单的方法是创建一个很小的临时文件来根据需要设置变量。这样的事情应该工作:
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
)
回答by nik
Double indirection (which is a very apt way pax
has put it) reminds of C pointer de-referencing.
I doubt that is supported in the Windows command shell.
双重间接(这是一种非常恰当的方式pax
)让人想起 C 指针取消引用。
我怀疑在Windows 命令外壳中是否支持。
Do you think the larger purpose you are targeting can be achieved with something easier;
maybe lesser of a code-golfapproach then the one contrived nicely by pax
?
您是否认为可以通过更简单的方式实现您所瞄准的更大目标?
也许较少的代码高尔夫方法然后精心设计的方法pax
?