0

First time posting so please be patient. I am trying to create a .bat file as follows

set a=file
set b=3
set file3=success
SETLOCAL ENABLEDELAYEDEXPANSION
echo %%a%!b!%

I was hoping it would parse as "echo %file3%" and would then print "success". Would appreciate guidance as to how to achieve the intended result. I would also appreciate it if someone could explain what actually happened.

mayer
  • 1
  • 3
    Possible duplicate of [Arrays, linked lists and other data structures in cmd.exe (batch) script](https://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script) – aschipfl Aug 06 '18 at 14:44
  • 5
    Quick answer: `echo !%a%%b%!`, or, to avoid delayed expansion, `call echo %%%a%%b%%%`; in both ways the inner variables become expanded prior to the outer ones... – aschipfl Aug 06 '18 at 14:45

2 Answers2

0

What you want to do with delayedExpansions is to expand one variable before an other. The one which should be expanded first is the one in %percentages%, the one which should be expanded delayed is in !exclamationMarks! (which can only be used while delayedExpansion is enabled).

So in your case you have to expand a and b first -> %a%%b% and then the value of both -> !file3!

combined: echo !%a%%b%!

timlg07
  • 547
  • 6
  • 20
0

The important thing for such, as I call them, nested variables is that the inner ones need to be replaced/expanded before the outer ones. Variables a and b are the ones I consider as the inner ones, and file3 is the outer one.

So using delayed expansion, we have two expansion phases available: the normal or immediate expansion (%) and the delayed expansion (!). Applying them in the said order the solution looks like this:

echo !%a%%b%!

So at first %a% is expanded to file and %b% to 3, hence the delayed expansion phase receives !file3!.


There is also a method that avoids delayed expansion: using call, which introduces another parsing phase where immediate expansion is repeated. The code looks like this:

call echo %%%a%%b%%%

So during the first normal expansion phase %% becomes replaced by a literal %, %a% becomes expanded to file, %b% to 3 and the remaining %% becomes again replaced by %; so we have %file3% left, which is expanded by the said second parsing phase due to call.


Both of the above methods imply normal expansion for the inner variables, which can cause problems when they are changed in a parenthesised block of code, like loop, for example. To avoid normal expansion we could use a for loop meta-variable, which is expanded later than normal expansion but before delayed expansion:

for %%I in ("!a!!b!") do echo !%%~I!

Or:

for /F "delims=" %%I in ("!a!!b!") do echo !%%I!

Since no immediate expansion is used herein, this would also work within another for loop even with changing variables a and b.

aschipfl
  • 33,626
  • 12
  • 54
  • 99