2

I find it an embarrassment when I want to use endlocal inside an if/for statement.

Please check this delayexpe.bat :

@echo off
setlocal EnableDelayedExpansion

set dvar=oldata

if "1" == "1" (
    REM Deliberately need a delayed-expansion context
    set dvar=newdata
    echo [1]=%dvar%
    echo [2]=!dvar!

    REM I want to set outvar for my calling environment, so I need endlocal.
    endlocal & ( set "outvar=!dvar!" )
    
    REM Normally, here will be an `exit /b 0`.
)

echo [3]outvar=%outvar%

exit /b 0

The output is:

[1]=oldata
[2]=newdata
[3]outvar=!dvar!

enter image description here

It means that delayed-expansion syntax !dvar! does not take effect on the same statement as endlocal, BUT, I need that endlocal because I now want to change my parent environment.

Moving endlocal outside the whole if block so to use endlocal & ( set "outvar=%some_temp_var%" ) may be a solution, but complicates the code flow.

I just can't figure out the reason why CMD refuse to expand !dvar! along side with endlocal. Can anyone clarify this?

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Jimm Chen
  • 3,411
  • 3
  • 35
  • 59
  • 2
    `For /f delims^= %%v IN ("!dvAR!") Do Endlocal & Set "returnvar=%%v"` – T3RR0R Mar 16 '22 at 07:42
  • 1
    the reason is that once the endlocal command has been parsed, if the calling environment does not have delayed expansion enabled, `!` is no longer considered a command token marking the beginning / end of a variable. – T3RR0R Mar 16 '22 at 07:44
  • @T3RR0R Thank you, your `For /f delims^=` trick do the right job for me. You can write it as answer. – Jimm Chen Mar 16 '22 at 07:53
  • 3
    It would be even easier to change the __IF__ condition to `if not "1" == "1" goto Label` and do not use a command block starting with `(` and ending with matching `)` at all which avoids also the need to use delayed expansion. – Mofi Mar 16 '22 at 08:43

0 Answers0