Return Values of Recursive Dynamic Variables in Batch
I'm attempting to use dynamic variables within Delayed Variable Expansion to represent other Dynamic Variables. I'm running into some trouble. How can I get a dynamic variable's value's value if the dynamic variable's value is another dynamic variable with it's own value?
i.e. !valA! = %valB% = this
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
...
...
FOR /F ... %%G IN (...) DO (
SET _temp=%%~nG
SET _file=!_temp:~0,-4!
SET _cnt=0
FOR /F ... %%L IN (...) DO (
SET _temp=%%L
SET _str=!_temp:*: =!
SET /A _cnt+=1
SET _temp=x!_file!!_cnt!
IF DEFINED !_temp! (
SET _temp=!%_temp%!
::
::_temp('s value) is _var('s value) is "xyz"
::Set new _temp to equal current _temp's "xyz"
::
开发者_开发知识库 IF !_temp! NEQ !_str! (
ECHO File Content Mismatch
)
) ELSE (
SET xvar=!_temp!
SET !xvar!=!_str!
)
)
)
...
...
exit
Any help would be appreciated.
Logically your failing code equates to
setlocal enableDelayedExpansion
(
set VAR1=success
set VAR2=VAR1
set VAR3=!%VAR2%!
echo VAR3=!VAR3!
)
As has already been pointed out in previous answers and comments, you can't assign a value to VAR2 and then access the value using %VAR2% within the same code block because %VAR2% is expanded during the parsing phase of the code block, at which point the value is not what you want (probably undefined).
But you need a second level of expansion in addition to !VAR2! to get the result you want. I know of three solutions.
1) This solution works, but it is not recommended because it is slow.
setlocal enableDelayedExpansion
(
set VAR1=success
set VAR2=VAR1
call set VAR3=%%!VAR2!%%
echo VAR3=!VAR3!
)
Prior to the execution of the CALL, each %% is reduced to %, and !VAR2! becomes VAR1.
Thus the called statement becomes set VAR3=%VAR1%
, and the called statement is reparsed through the %var% expansion phase, so you get your desired result.
BUT - CALL is relatively very expensive. When used in a loop it can cause severe performance degradation. jeb provides a good demonstration and explanation at CALL me, or better avoid call
1a) There is a variation of the CALL solution where you call a :LABELed subroutine. Because the subroutine is parsed after the call, you can simply use set VAR3=!%VAR2%!
. But again, this uses CALL so it is relatively slow and not recommended.
2) This general solution works, and is MUCH faster in comparison. It uses a FOR variable for the second level of expansion. This is the recommended solution.
setlocal enableDelayedExpansion
(
set VAR1=success
set VAR2=VAR1
for /f %%A in ("!VAR2!") do set VAR3=!%%A!
echo VAR3=!VAR3!
)
3) If the value of VAR1 is known to be an integer, then there is a special case solution using SET /A
setlocal enableDelayedExpansion
(
set VAR1=999
set VAR2=VAR1
set /a VAR3=!VAR2!
echo VAR3=!VAR3!
)
The SET /A command has its own built in expansion of variables that takes place after delayed expansion, and no punctuation is needed.
Your code fails at SET _temp=!%_temp%!
, as the percent expansion is evaluated while parsing the parenthesis block.
You could change it to
set "varname=!_temp!"
set "content=!varname!"
Btw. It would be much easier, if your sample would be reduced to the minimum of code, like.
setlocal EnableDelayedExpansion
set "var1=content of var1"
set "var2=var1"
set "result=!%var2%!"
echo !result!
This only works as it isn't in brackets.
To better understand how the different expansions work,
you can read How does the Windows Command Interpreter (CMD.EXE) parse scripts?
精彩评论