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.