goto within block forces var re-evaluation

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Sponge Belly
Posts: 234
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

goto within block forces var re-evaluation

#1 Post by Sponge Belly » 04 Feb 2013 10:09

Greetings!

I read an interesting Experts Exchange topic. Search for the Goto Issue section. The example given by Qlemo goes something like this:

Code: Select all

set fruit=apples
if 1==1 (
echo(%fruit%
set fruit=bananas
goto nextline
:nextline
echo(%fruit%
)


Pretty cool, huh? ;-) But wait, it gets better! I thought this trick would only work inside conditional or bare blocks, but FoxiDrive’s recent post on problem with a label in parentheses proves that you can use labels inside for loops so long as the label isn’t the last statement in the block. :shock:

This leaves the door open to commit such attrocities as:

Code: Select all

setlocal enabledelayedexpansion
set "string=!%~1!" & set "substr=!%~2!"

for %%v in (string substr) do (
set "var=!%%v!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~3!"
if not defined notdelayed set "var=!var:^=^^^^!"
goto nextline
:nextline
if not defined notdelayed set "var=%var:!=^^^!%" !
set "%%v=!var!"
)
endlocal


The above isn’t a standalone working example, but you get the idea. ;-) Apologies to Jeb for mangling his “safe string return” code.

Hope you find this useful.

- SB
Last edited by Sponge Belly on 24 Feb 2013 09:03, edited 1 time in total.

jeb
Expert
Posts: 1058
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: goto within block forces var re-evaluation

#2 Post by jeb » 04 Feb 2013 12:20

Hi Sponge Belly,

Sponge Belly wrote:Code:
set fruit=apples
if 1==1 (
echo(%fruit%
set fruit=bananas
goto nextline
:nextline
echo(%fruit%
)


Pretty cool, huh? ;-)

It looks confusing, but the cause is simple:
A goto breaks a block, or better it leaves even the deepest nested blocks.

So effectively it's the same as:

Code: Select all

set fruit=apples
if 1==1 (
set fruit=bananas
echo(%fruit%
)
rem goto nextline
rem :nextline
echo(%fruit%
rem )


Sponge Belly wrote:But wait, it gets better! I thought this trick would only work inside conditional or bare blocks, but FoxiDrive's recent post on problem with a label in parentheses proved that you can use labels inside for loops so long as the label isn't the last statement in the block. :shock:


Yes, this is a bit more complicated, but even this follows some strange rules :)
Labels in blocks are two line oriented, a primary line (the label) and a secondary line.
A label in a block starts the two line logic, and requires a a secondary line.
In the simplest case the secondary line is a command, then all seems to be normal

Code: Select all

(
:myLabel
echo hello


But the secondary line must be a valid command line.
That's the cause why a simple closing brackt fails, and also a double colon will fail, but not a single colon.

And additionally in the secondary line labels are interpreted a bit different.

Code: Select all

(
:primaryLabel & echo this is a comment
:secondaryLabel & echo But this will be printed!
)


hope I could brought light into the darkness

jeb

Post Reply