1

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.

2 Answers2

1

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.

dbenham
  • 119,153
  • 25
  • 226
  • 353
  • I ended up solving it another way, but I have forgotten what it was because I since quit that job. – seantmanley May 23 '13 at 00:55
  • I think I lied after re-reading this. I am not sure, but I _think_ I went with something along the lines of your #2 @dbenham. I remember it took me a few days to mull over and get it working. I'm going to try to get ahold of some of the old scripts so I can see what it was that I actually did. Thanks for the help so long ago. :) – seantmanley May 10 '14 at 08:14
0

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?

Community
  • 1
  • 1
jeb
  • 70,992
  • 15
  • 159
  • 202
  • The code block is parsed from a larger block of code that does not play well with others when using calls to other functions. C'est la vie. Cheers. – seantmanley Oct 06 '11 at 18:50