Page 1 of 1

Delayed Expansion in Subs- Again

Posted: 31 Oct 2015 23:36
by lmstearn
Just a note on Delayed Expansion (mentioned countless times before but...)

Code: Select all

@echo off & SETLOCAL ENABLEDELAYEDEXPANSION
SET _STRING=to be replaced
SET _NEWSTRING=not replaced
IF TRUE==TRUE (
SET "_NEWSTRING=!_STRING:to be r=r!"
@echo "%_STRING%" "%_NEWSTRING%"
pause >nul
) else (
@echo nada
pause >nul
)

@echo "%_STRING%" "%_NEWSTRING%"
pause >nul

The value of _NEWSTRING is not updated until the IF sub exits. Can be an annoyance if debugging. :roll:

Re: Delayed Expansion in Subs- Again

Posted: 01 Nov 2015 07:12
by aGerman
Imstearn wrote:@echo "%_STRING%" "%_NEWSTRING%"

As you should know the syntax of a variable will change if delayed expansion is defined. The reason for the delayed expansion is that you can access the current value of a variable that was changed in the same command line or the same (in parentheses enclosed) block of command lines. In that case you have to define delayed expansion and you have to replace the percent signs with exclamation marks. Hence the question is where are the exclamation marks?

(EDIT: For whatever reason I deleted this post. So I just tried to remember the text that I wrote ...)

Re: Delayed Expansion in Subs- Again

Posted: 01 Nov 2015 08:44
by lmstearn

Code: Select all

@echo off & SETLOCAL ENABLEDELAYEDEXPANSION
SET _STRING=to be replaced
SET _NEWSTRING=not replaced
IF TRUE==TRUE (
SET "_NEWSTRING=%_STRING:to be r=r%"
@echo "%_STRING%" "%_NEWSTRING%"
pause >nul
) else (
@echo nada
pause >nul
)

@echo "%_STRING%" "%_NEWSTRING%"
pause >nul

The same effect. The aim is to avoid bangs for the moment. :)

Re: Delayed Expansion in Subs- Again

Posted: 01 Nov 2015 08:56
by aGerman
The question remains the same...
aGerman wrote:where are the exclamation marks?

Something to play with:

Code: Select all

@echo off &setlocal EnableDelayedExpansion
set "var=0"

echo before: %var%
echo ~~~~

for /l %%i in (1 1 10) do (
  set "var=%%i"
  echo with percent signs:     %var%
  echo with exclamation marks: !var!
  echo ~~~~
)

echo after: %var%
pause

The body of a loop or of an if statement is a block of command lines that is enclosed into parentheses. Please reread my first reply.

BTW a proper line indentation will help you to realize that you are in a block of command lines and it will help to avoid unpaired parentheses.

Regards
aGerman

Re: Delayed Expansion in Subs- Again

Posted: 01 Nov 2015 13:38
by Aacini
lmstearn wrote: The aim is to avoid bangs for the moment.


This should work

Code: Select all

@echo off
SET _STRING=to be replaced
SET _NEWSTRING=not replaced
IF TRUE==TRUE (
CALL SET "_NEWSTRING=%%_STRING:to be r=r%%"
@CALL echo "%%_STRING%%" "%%_NEWSTRING%%"
pause >nul
) else (
@echo nada
pause >nul
)

@echo "%_STRING%" "%_NEWSTRING%"
pause >nul

HOWEVER if previous code will be executed in the command-line context, I think you must change the double percents by single ones. You must do a test on this point!

Antonio

Re: Delayed Expansion in Subs- Again

Posted: 01 Nov 2015 22:10
by foxidrive
lmstearn wrote:The aim is to avoid bangs for the moment. :)


Bangs is what you do in dodgem cars. Your linked post made no sense to me, using the word bangs.

Re: Delayed Expansion in Subs- Again

Posted: 01 Nov 2015 22:53
by lmstearn
That's fine. The only thing that puzzles is that the static nomenclature hasn't been revised in years. I'm sure there was an ancient blurb that explained it all, but delayed expansion? Without using bangs the expansion is taken to the first point outside the sub. "Delayed" expansion as opposed to "instantaneous" expansion.
Something like "execute_expansion" an improvement?

Re: Delayed Expansion in Subs- Again

Posted: 02 Nov 2015 05:35
by aGerman
The reason for this wording is pretty simple. Normally a variable will be expanded to its value before the command line or the block of command lines is executed. That's the reason why you cannot access the changed value immediatelly in the same line or block. Delayed expansion means that the variable will be expanded later during the execution of the line or block. That's only a rough explanation though. If you want to have a detailed insight you may read that thread on SO:
http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/4095133#4095133

Regards
aGerman

Re: Delayed Expansion in Subs- Again

Posted: 03 Nov 2015 04:22
by lmstearn
Yeah, Aacini's example posted above is what I consider a classic case of "delayed expansion" without it ever turned on. :P
But TBQH the material collated on this, and related topics on cmd in this site and SO amounts are quite voluminous. Sites like Robvandwoude and SS64 also give pretty good coverage, but encore, encore!
Case in point is the post you quoted, but that alone can be expanded (along with illustrative examples) to fill a good sized book.

Re: Delayed Expansion in Subs- Again

Posted: 07 Nov 2015 11:25
by Samir
Delayed expansion can be a real bane for me. Always great to see refreshes on the subject. 8)

Re: Delayed Expansion in Subs- Again

Posted: 07 Nov 2015 11:48
by aGerman
Have a look at my examples at the end of this thread:
viewtopic.php?f=3&p=36882
aGerman wrote:Rough rule of thumb:
Assigning a variable is safe with delayed expansion disabled. Working with the assigned variable is safe with delayed expansion enabled.

Re: Delayed Expansion in Subs- Again

Posted: 07 Nov 2015 15:57
by Samir
aGerman wrote:Have a look at my examples at the end of this thread:
viewtopic.php?f=3&p=36882
aGerman wrote:Rough rule of thumb:
Assigning a variable is safe with delayed expansion disabled. Working with the assigned variable is safe with delayed expansion enabled.
Will do!

Rule of thumb for me is--if there's a problem, use a bunch of echos to figure out what's wrong. :mrgreen:

Re: Delayed Expansion in Subs- Again

Posted: 07 Nov 2015 16:51
by trebor68
Your code updated.

Code: Select all

@echo off & SETLOCAL ENABLEDELAYEDEXPANSION
SET _STRING=to be replaced
SET _NEWSTRING=not replaced
IF TRUE==TRUE (
SET "_NEWSTRING=%_STRING:to be r=r%"
echo "%_STRING%" "%_NEWSTRING%"  ##  "%_STRING%" "!_NEWSTRING!"
IF "!_NEWSTRING!"=="replaced" (echo The string is replaced.) & echo.
pause >nul
) else (
echo nada
pause >nul
)

echo "%_STRING%" "%_NEWSTRING%"
pause >nul


The variable %_NEWSTRING% is only changed when the IF construct is exited (delayed).
The variable !_NEWSTRING! is varied within the IF construct.