1.

Solve : Nested variable / argument expansion?

Answer»

I think this is do-able, I just don't know the syntax...

First, the basics:
Code: [Select]@ECHO OFF
CLS
;
VERIFY OTHER 2>NUL
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (
ECHO Cannot enable COMMAND Extensions
GOTO EndError
)
;
VERIFY OTHER 2>NUL
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 (
ECHO Cannot enable Delayed Environment Variable Expansion
GOTO EndError
)
Now set a few variables:
Code: [Select]IF NOT DEFINED TEST SET TEST=C:\Temp
IF NOT DEFINED Test1 SET Test1=%TEST%\Test123
IF NOT DEFINED TestABC SET TestABC=%TEST%\TestXYZ
IF NOT DEFINED TestFoo SET TestFoo=%TEST%\TestFoo
IF NOT DEFINED TestBad SET TestBad=%TEST%\NoSuchThing
See what's what:
Code: [Select]ECHO.
ECHO TEST = %TEST%
ECHO Test1 = %Test1%
ECHO TestABC = %TestABC%
ECHO TestFoo = %TestFoo%
ECHO TestBad = %TestBad%
ECHO.
What I get:
TEST = C:\Temp
Test1 = C:\Temp\Test123
TestABC = C:\Temp\TestXYZ
TestFoo = C:\Temp\TestFoo
TestBad = C:\Temp\NoSuchThing

What I'm trying to do here is nest the arguments. In other words, I want an argument1 to EXPAND to the NAME of argument2, which in turn should expand to the VALUE of argument2. Example:
Code: [Select]FOR %%d IN (Test1 TestABC TestFoo TestBad) DO (
SET ThisArg=%%d
ECHO ThisArg = !ThisArg!

SET ThisArgValue=UNKNOWN
ECHO ThisArgValue = !ThisArgValue!
)

What I get:
ThisArg = Test1
ThisArgValue = UNKNOWN

ThisArg = TestABC
ThisArgValue = UNKNOWN

ThisArg = TestFoo
ThisArgValue = UNKNOWN

ThisArg = TestBad
ThisArgValue = UNKNOWN

What I WANT:
ThisArg = Test1
ThisArgValue = C:\Temp\Test123

ThisArg = TestABC
ThisArgValue = C:\Temp\TestXYZ

ThisArg = TestFoo
ThisArgValue = C:\Temp\TestFoo

ThisArg = TestBad
ThisArgValue = C:\Temp\NoSuchThing

See it? On the first iteration, %%d resolves to the string value Test1.

I want ThisArgValue to resolve to !Test1! -- in other words, the VALUE of %%d, not the "name" or "string" of %%d.

In turn, !ThisArgValue! (note the !difference!) should resolve to %TEST%\Test1 == C:\Temp\Test1.

Intuitively, the expansion I'm looking for would be written as:
%(%%d)%

or

!(%%d)!

using Delayed Expansion... but that syntax doesn't work. Neither does any combination of ~tilde, (parenthesis), [brackets] or !%bookends%! I've tried.

Help??? Many thanks.
The solution involves CALL and double percent signs.

Modifying your code slightly, (but also see below***)

I only show the LOOP, since the rest is identical to your code which you posted above.

Code: [Select]FOR %%d IN (Test1 TestABC TestFoo TestBad) DO (
set thisarg=%%d
ECHO ThisArg = !ThisArg!

REM Note (1) CALL
REM Note (2) Percent signs..
REM Note (3) ...Doubled up
call SET ThisArgValue=%%!Thisarg!%%

ECHO ThisArgValue = !ThisArgValue!
echo.
)
Output

Code: [Select]TEST = C:\Temp
Test1 = C:\Temp\Test123
TestABC = C:\Temp\TestXYZ
TestFoo = C:\Temp\TestFoo
TestBad = C:\Temp\NoSuchThing

ThisArg = Test1
ThisArgValue = C:\Temp\Test123

ThisArg = TestABC
ThisArgValue = C:\Temp\TestXYZ

ThisArg = TestFoo
ThisArgValue = C:\Temp\TestFoo

ThisArg = TestBad
ThisArgValue = C:\Temp\NoSuchThing
*** see here

Quote

Intuitively, the expansion I'm looking for would be written as:
%(%%d)%

... You're nearly there! Just use CALL and double up the percents as in this alternative to above loop:

Code: [Select]FOR %%d IN (Test1 TestABC TestFoo TestBad) DO (
set thisarg=%%d
call set thisargvalue=%%%%d%%
ECHO ThisArg = !ThisArg!
ECHO ThisArgValue = !ThisArgValue!
echo.
)

To be echoed or otherwise invoked, percent signs, being special characters, need 'escaping'; the escape character is... another percent sign, then you use call (or CALL as you seem to prefer) to pass the command to a child cmd thus %%variablename%% becomes %variablename% which is expanded to the variable's value.

You did know that it is not OBLIGATORY to write batch code in ALL UPPER CASE? (Just a stylistic preference I guess)







Yeah, the CAPS are just for style. CALL SET makes perfect sense. OUTSTANDING! Many thanks!!!


Discussion

No Comment Found