Guinness
Guinness

Reputation: 97

variable as tokens in for loop

Im trying to make a batch file that loops thru an array containing numbers like this: 1 2 3 4 5. In the first itteration of the loop I like to pick token 1 and 2. In the second 2 and 3, in the third 3 and 4 and so on.

I do think I should use ! in the variables first and second that I use as tokens. Like in the first FOR /F, but when I do, I get: !first!" was not expected here.

And if I use %, it does not count up. Everything works except the variable tokens. Any one knowes how to? Any help or suggestions greatly appriciated. This is the part Im struggeling with:

setlocal EnableDelayedExpansion
set first=1
set second=2
set N=4
set output="1 2 3 4 5"
set output=%output:"=%

for /L %%a in (1,1,%N%) do (
    if !counter! equ active (
        set /a first+=1
        set /a second+=1
    )
        FOR /F "tokens=!first!" %%a IN ("%output%") DO (
        set nr1=%%a
        )
        FOR /F "tokens=%second%" %%a IN ("%output%") DO (
        set nr2=%%a
        )

    echo nr1 var: !nr1!
    echo nr2 var: !nr2!
    echo counter f: !first!
    echo counter s: !second!
    set counter=active
)

Upvotes: 3

Views: 626

Answers (1)

aschipfl
aschipfl

Reputation: 34909

You cannot use delayed expanded variables in the options string of for /F. Neither can you use other for variables for that. But you can use normally (immediately) expanded variables. Also you can use argument references like %1, for example.

So a nice work-around for your problem is to place the for /F loop in a sub-routine and use call in the main program with the delayed expanded variables as arguments, like this:

@echo off
setlocal EnableDelayedExpansion
set /A first=1
set /A second=2
set /A N=4
set "output=1 2 3 4 5"

set "counter="
for /L %%a in (1,1,%N%) do (
    if defined counter (
        set /A first+=1
        set /A second+=1
    )

    call :SUB !first! !second!

    echo nr1 var: !nr1!
    echo nr2 var: !nr2!
    echo counter f: !first!
    echo counter s: !second!
    set "counter=active"
)
endlocal
exit /B

:SUB  val_token1  val_token2
for /F "tokens=%~1,%~2" %%a in ("%output%") do (
    if %~1 LSS %~2 (
        set "nr1=%%a"
        set "nr2=%%b"
    ) else if %~1 GTR %~2 (
        set "nr1=%%b"
        set "nr2=%%a"
    ) else (
        set "nr1=%%a"
        set "nr2=%%a"
    )
)
exit /B

Since you are extracting tokens from the same string, I combined your two for /F loops into a single one. The if block in the for /F loop in the sub-routine :SUB is there just in case the second token number is not always greater than the first one. But if that can guaranteed, the for /F loop needs to contain only set "nr1=%%a" and set "nr2=%%b".

Upvotes: 2

Related Questions