Delayed Expansion in Subs- Again

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Delayed Expansion in Subs- Again

#1 Post by lmstearn » 31 Oct 2015 23:36

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:

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Delayed Expansion in Subs- Again

#2 Post by aGerman » 01 Nov 2015 07:12

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 ...)

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Delayed Expansion in Subs- Again

#3 Post by lmstearn » 01 Nov 2015 08:44

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. :)

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Delayed Expansion in Subs- Again

#4 Post by aGerman » 01 Nov 2015 08:56

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

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Delayed Expansion in Subs- Again

#5 Post by Aacini » 01 Nov 2015 13:38

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

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Delayed Expansion in Subs- Again

#6 Post by foxidrive » 01 Nov 2015 22:10

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.

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Delayed Expansion in Subs- Again

#7 Post by lmstearn » 01 Nov 2015 22:53

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?

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Delayed Expansion in Subs- Again

#8 Post by aGerman » 02 Nov 2015 05:35

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

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Delayed Expansion in Subs- Again

#9 Post by lmstearn » 03 Nov 2015 04:22

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.

Samir
Posts: 384
Joined: 16 Jul 2013 12:00
Location: HSV
Contact:

Re: Delayed Expansion in Subs- Again

#10 Post by Samir » 07 Nov 2015 11:25

Delayed expansion can be a real bane for me. Always great to see refreshes on the subject. 8)

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Delayed Expansion in Subs- Again

#11 Post by aGerman » 07 Nov 2015 11:48

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.

Samir
Posts: 384
Joined: 16 Jul 2013 12:00
Location: HSV
Contact:

Re: Delayed Expansion in Subs- Again

#12 Post by Samir » 07 Nov 2015 15:57

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:

trebor68
Posts: 146
Joined: 01 Jul 2011 08:47

Re: Delayed Expansion in Subs- Again

#13 Post by trebor68 » 07 Nov 2015 16:51

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.

Post Reply