1

In the following code I create some pseudo array (representing pairs) and call a routine which gets the name of the pseudo array and its size as parameter values. In the routine I want to access each array element in a loop. To my knowledge the only possibility to access the array values is to use delayed expansion which would not be problem if i could get back the value of the delayed expansion local.

@ECHO OFF
    SETLOCAL DISABLEDELAYEDEXPANSION
        set pairs[0]="a" "b"
        set pairs[1]="c" "d"
        set pairs[2]="e" "f"
        set pairNumber=3

        call :my_routine pairs %pairNumber%
    ENDLOCAL
EXIT /B 0

:my_routine
    SETLOCAL DISABLEDELAYEDEXPANSION
        set myPairs=%1
        set /a maxCount=%2-1

        for /l %%c in (0,1,%maxCount%) do (
            set "currentPair="
            SETLOCAL ENABLEDELAYEDEXPANSION
                call set "pair=%%!myPairs![%%c]%%"
                REM setting the value works:
                REM echo !pair!
            ENDLOCAL & set "currentPair=%pair%"
            echo %currentPair%
        )
    ENDLOCAL
exit /b 0

Expected Output:

"a" "b"
"c" "d"
"e" "f"

The crucial part is & set currentPair=%pair%. To my understanding the %pair% value is not set because of using delayed expansion when setting it.

The question is about getting the value back NOT about telling me that I could do stuff in the local itself. This is something i would consider if there is no way to get the value back.

I also took a look at this very similiar question but the solution does not work for me.

So...

How do i get the value out of the inner local so that currentPair gets the value of pair?

goulashsoup
  • 2,639
  • 2
  • 34
  • 60
  • 3
    You've had enough help and advice thus far to know that the recommended syntax for setting variables is `Set "Variable=Value"` and if that variable is being undefined/emptied `Set "Variable="`. _There's a good reason why it is recommended!_ – Compo Jun 15 '18 at 20:35
  • @Compo Well, I know that it is possible to use the `Set "Variable=Value"` although i still don't know why it is recommended... But i edited with the _right_ way anyway. So what is the good reason? – goulashsoup Jun 15 '18 at 20:57
  • 2
    @goulashsoup Please read the answer on [Why is no string output with 'echo %var%' after using 'set var = text' on command line?](https://stackoverflow.com/a/26388460/3074564) There is explained in detail why `Set "Variable=Value"` is recommended as long as __command extensions__ are enabled as by default. – Mofi Jun 15 '18 at 21:44

2 Answers2

2

The usual way of passing a variable value beyond the endlocal barrier relies on the fact that it is not placed within a block of code, but you placed the line endlocal & set "currentPair=%pair%" within a for /L loop.

You can use a for /F loop instead, like this:

for /F "delims=" %%E in (""!pair!"") do (
    endlocal
    set "currentPair=%%~E"
)

The outer pair of quotes around !pair! tells for /F that it is a literal string; the inner pair is part of that string, which is then removed by the ~ modifier in %%~E. The purpose of this is to ensure that the loop always iterates once (even when !pair! is empty), and so endlocal becomes executed.

This also works in another block of code like your for /L loop.

Of course the line echo %currentPair% does not return the correct string, but you could place echo(%%~E within the for /F loop instead.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
1

I'm sure this will not be what you wanted; but based upon limited information you've provided, and the known string content, there is no need to be setting unnecessary variables or enabling and disabling delayed expansion within the For /L loop.

@Echo Off
SetLocal DisableDelayedExpansion

Set "pairs[0]="a" "b""
Set "pairs[1]="c" "d""
Set "pairs[2]="e" "f""
Set "pairNumber=2"

Call :my_routine pairs %pairNumber% currentPair

Exit /B 0

    :my_routine
    SetLocal EnableDelayedExpansion

    For /L %%A In (0,1,%2) Do Set "%3=!%1[%%A]!" & Echo !%3!

    Pause

    Exit /B 0

You can optionally change Echo !%3!to Set %3 if required
Each SetLocal will EndLocal with their respective Exit

Compo
  • 36,585
  • 5
  • 27
  • 39