Michael Zhang
Michael Zhang

Reputation: 25

How to use %% inside %% in batch file? I know it's a little confused, click in

I know the question is a little confusing. This is my script. (easy version)

I've set up those variables

p1 = 1
p2 = 0
p3 = 1

and it goes on and on. I want to show a list of all of those P values. Then, I setup a variable "i"

set /a i = 0
:loop
set /a i = %i% + 1
echo P%i% = %p%i%%
goto loop

but then I realized that %p%i%% is not working... It won't go to %p1% and show me "1", it just shows me %p1%. and in my full script, it shows me something crazy... SO CAN ANYONE HELP ME OUT HERE?? THANKS A LOT!!

Upvotes: 1

Views: 385

Answers (2)

Mofi
Mofi

Reputation: 49127

I offer two more solutions in addition to the solutions in answer of jeb not using delayed expansion:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "MyP1=1"
set "MyP2=0"
set "MyP3=5"

set "Count=0"
for /F "tokens=1* delims==" %%I in ('set MyP 2^>nul') do echo Variable %%I has value %%J & set /A Count+=1
echo Variables count is: %Count%

echo/
set "Index=1"

:Loop
if not defined MyP%Index% goto ExitLoop
set /A Value=MyP%Index%
echo Variable MyP%Index% has value %Value%
set /A Index+=1
goto Loop

:ExitLoop
set /A Index-=1
echo Variables count is: %Count%
endlocal
echo/
pause

The environment variables with undetermined number start all with the string MyP. The first approach runs set MyP in a separate command process in background which outputs all environment variables starting with MyP with their values sorted alphabetically, i.e. the output is for this batch code:

MyP1=1
MyP2=0
MyP3=5

This output is processed line by line by FOR which splits each line up into two substrings because of delims== with first substring being name of the environment variable assigned to loop variable I and everything after first equal sign in the line assigned to next loop variable J according to ASCII table which is the value of the environment variable because of tokens=1*.

The names of the environment variables and their values are output with counting the number of variables starting with MyP which is also output after the FOR loop.

The number of the environment variables must not be consecutive increasing for the first solution.

The second solution uses a loop without FOR. This loop requires that the environment variables have an incrementing number in their names. The loop exits if there is no more environment variable with current index number in name.

The value of the current environment variable is assigned to environment variable Value using an arithmetic expression because in this case a string like MyP1 in the arithmetic expression is interpreted as name of an environment variable whose value should be converted to an integer for evaluation of the expression. The integer result of the arithmetic expression is converted back to a string and assigned to the environment variable left to the equal sign.

The answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? might be helpful to understand the environment variables usage techniques as used here.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • setlocal /?

See also Single line with multiple commands using Windows batch file for an explanation of & operator used on FOR command line to avoid the need of a command block.

Upvotes: 1

jeb
jeb

Reputation: 82337

Two simple ways. The first is to use delayed expansion. First expand i with %i% and later the expression !p1!

Or use CALL to parse a line a second time.
The line call echo P%i% = %%p%i%%% after the first parse looks like call echo P1 = %p1% The second parse will expand %p1% to the content.

setlocal EnableDelayedExpansion
set p1=1
set p2=0
set p3=1

set /a i = 0
:loop
set /a i = %i% + 1
echo P%i% = !p%i%!
call echo P%i% = %%p%i%%%
if %i% == 3 exit /b
goto loop

Or another solution using a for loop

for /L %%i in (1 1 3) do (
    echo P%%i = !p%%i!
)

Upvotes: 2

Related Questions