I am trying to double my delayed expansion if that makes any sense. Here is what I want.
set var1=hello
set var2=var1
set var3=var2
echo %!%var3%!%
and then have hello
be displayed. This is not my actual code but an example of how I need it to work.
even possible without delayed expansion (although even uglier than rojo's answer) Just a matter of the number of "layers" of parsing and correct escaping the %
:
@echo off
set var1=hello
set var2=var1
set var3=var2
call call echo %%%%%%%var3%%%%%%%
Another one without call
(faster):
@echo off
setlocal enabledelayedexpansion
set "var1=hello"
set "var2=var1"
set "var3=var2"
for %%v in (!%var3%!) do echo !%%v!
EDIT: Reply to rojo's challenge
Your code have an error in the creation of the variables; all variables contain the string: "var!X!" and the final result is "var!X!X". Below is your code with the variables creation part fixed:
@echo off
setlocal EnableDelayedExpansion
set "var1=hello"
for /L %%I in (2,1,1000) do (
set /a X = %%I - 1
set "var%%I=var!x!"
)
call :follow var1000
goto :EOF
:follow <varname>
setlocal enabledelayedexpansion
set "var=!%~1!"
:follow_loop
if defined !%var%! (
set "var=!%var%!" & goto follow_loop
) else (
echo !%var%!
)
This program correctly show "hello" at end; it takes about 2.51 seconds when run in my computer.
The method is pretty short, so there is not too much chance to improve it; the obvious modification is to change the goto
loop by a for
(while) one. Here it is:
@echo off
setlocal EnableDelayedExpansion
set "var1=hello"
for /L %%I in (2,1,1000) do (
set /a X = %%I - 1
set "var%%I=var!x!"
)
call :follow var1000
goto :EOF
:follow <varname>
set "var=%~1"
cmd /V:ON /C for /L %%? in () do @for %%v in (^^!var^^!) do @if defined %%v (set "var=^!%%v^!") else echo %%v ^& exit
This code takes about 1.22 seconds to run, that is, just the 48.6% of your method (2 times faster) ;)
You could add a call
and surround your first delayed expansion with double percents like this.
@echo off
setlocal enabledelayedexpansion
set "var1=hello"
set "var2=var1"
set "var3=var2"
call echo %%!%var3%!%%
Seems horribly convoluted to me, though. I'd probably rewrite the script to make such trickery not needed if I were me.
Edit: Since there are so many solutions being added here, I'll propose another one. Here's a subroutine that will follow the line of variables from beginning to end, even if it's 1000 levels deep. Just as an academic exercise.
@echo off
setlocal
set "var1=hello"
for /L %%I in (2,1,1000) do (
set /a X = %%I - 1
setlocal enabledelayedexpansion
for %%x in (!X!) do endlocal & set "var%%I=var%%x"
)
call :follow var1000
goto :EOF
:follow <varname>
setlocal enabledelayedexpansion
set "var=!%~1!"
:follow_loop
if defined !%var%! (
set "var=!%var%!" & goto follow_loop
) else (
echo !%var%!
)
And here's another using a batch + JScript hybrid (because the JScript while
loop is faster than a batch goto
loop).
@if (@CodeSection == @Batch) @then
@echo off
setlocal
set "var1=hello"
for /L %%I in (2,1,1000) do (
set /a X = %%I - 1
setlocal enabledelayedexpansion
for %%x in (!X!) do endlocal & set "var%%I=var%%x"
)
cscript /nologo /e:JScript "%~f0" "var1000"
goto :EOF
@end // end batch / begin JScript hybrid chimera
var env = WSH.CreateObject('Wscript.Shell').Environment('Process'),
itm = WSH.Arguments(0);
while (env(itm)) itm = env(itm);
WSH.Echo(itm);
Your move, Aacini.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With