1

I have a little problem and can't get my head to make it work. Here is the code:

SET onts=3

SET port[1]=0
SET port[2]=3
SET port[3]=2

SET free[0]=8
SET free[1]=5
SET free[2]=5
SET free[3]=15

FOR /L %%A IN (1,1,%onts%) DO (
    SET /A ont[%%A]=%free[%port[%%A]%]%
)

echo %ont[1]%
echo %ont[2]%
echo %ont[3]%

I expect that code takes on first loop iteration value 0 of variable port[1] as index and so accessing variable free[0] to assign its value 8 to variable ont[1]. On second iteration value 3 of variable port[2] should be used to get value 15 assigned to variable free[3] assigned next to variable ont[2]. And on third iteration the variable ont[3] should be defined with value 5 from free[2] after reading value 2 from port[3].

So the output should be:

8
15
5

But the batch file outputs:

0
3
2

I've tried using a second variable in loop:

SET /A var1 = %port[%%A]%
SET /A ont[%%A]=%free[%var1%]%

But it didn't work either.

I've also tried calling a function to outsource this code, but still no result - this one I'm not sure, I have perhaps done something wrong.

Has anybody any idea on how to make it work?

Mofi
  • 38,783
  • 14
  • 62
  • 115
John Doe
  • 47
  • 4

2 Answers2

2

I suggest to first read How does the Windows Command Interpreter (CMD.EXE) parse scripts?.

Windows command processor parses an entire command block starting with ( and ending with matching ) and replaces all value references of environment variables done with %variable% by current value of the environment variable respectively nothing on environment variable not existing.

This means for command line SET /A ont[%%A]=%free[%port[%%A]%]% that cmd.exe interprets %free[% as value reference of environment variable named free[ and %]% as value reference of environment variable named ] before executing command FOR. There is neither an environment variable free[ nor ] defined above FOR command line and it can be expected that such environment variables do not exist at all before starting the batch file. For that reason Windows command processor executes finally after preprocessing phase the command line:

FOR /L %A IN (1 1 3) DO (SET /A ont[%A]=port[%A] )

This can be seen on running the batch file exactly as posted (without @echo off as usually used as first command line) in a command prompt window.

One solution is using delayed expansion and one more FOR loop to get value of free[y] depending on value of port[x] assigned to an environment variable ont[x].

@echo off
setlocal EnableExtensions EnableDelayedExpansion

set "onts=3"

set "port[1]=0"
set "port[2]=3"
set "port[3]=2"

set "free[0]=8"
set "free[1]=5"
set "free[2]=5"
set "free[3]=15"

for /L %%A IN (1,1,%onts%) do for %%B in (!port[%%A]!) do set "ont[%%A]=!free[%%B]!"

echo %ont[1]%
echo %ont[2]%
echo %ont[3]%
endlocal

The output of this batch file is:

8
15
5

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 /?
  • set /?
  • setlocal /?

Last I suggest to read answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line?

Mofi
  • 38,783
  • 14
  • 62
  • 115
1

Your approach needs two (with the code block in fact three) levels of delayed expansion, you are using none.

My previous answer demonstrated how to use delayed expansion

Mofis good answer shows one way to overcome double delayed expansion with a for,
here is another one with a pseudo call:

:: Q:\Test\2018\11\24\SO_53458343.cmd
@Echo off&SetLocal EnableExtensions EnableDelayedExpansion
SET onts=3

SET port[1]=0
SET port[2]=3
SET port[3]=2

SET free[0]=8
SET free[1]=5
SET free[2]=5
SET free[3]=15

FOR /L %%A IN (1,1,%onts%) DO Call SET /A "ont[%%A]=%%free[!port[%%A]!]%%"

echo ont[1]=%ont[1]%
echo ont[2]=%ont[2]%
echo ont[3]=%ont[3]%

> Q:\Test\2018\11\24\SO_53458343.cmd
ont[1]=8
ont[2]=15
ont[3]=5