Is there any way to modify a variable twice in the same IF comparison?

Microsoft Windows
Post Reply
Rekrul
Posts: 52
Joined: 2021-Aug-15, 11:29 pm

Is there any way to modify a variable twice in the same IF comparison?

Post by Rekrul »

Is there any way you can modify a variable twice as the result of a single if comparison, WITHOUT using Delayed Expansion?

For example;

Code: Select all

@echo off

set x=1
set test=Hello

if %x% equ 1 (
set test=Hi
set test=%test% There
)
echo %test%
This prints Hello There if the comparison is true, and just Hello if it's not. The first set command is being ignored.

If I change it to;

Code: Select all

@echo off

set x=2
set test=Hello

call if %x% equ 1 (
set test=Hi
set test=%test% There
)
echo %test%
It prints Hi There regardless of the comparison. So apparently the if comparison is being ignored and it just executes the set commands regardless.

to make it work reliably, I have to use;

Code: Select all

@echo off

set x=2
set test=Hello

if %x% equ 1 (
set test=Hi
)
if %x% equ 1 (
set test=%test% There
)
echo %test%
Is there some way around this, or are you required to use two separate if comparisons to conditionally modify a variable twice?

For the curious: I was making a script to number sets of files and I wanted it to pad the counter with leading zeroes if there were more than nine files in a set. So I had it count them and set a flag if there were more than nine files. Then if that flag was set, it would add a zero to the start of the variable and then truncate it to the last two characters, giving me a two-digit counter. As above, this didn't work unless I used two separate comparisons.
User avatar
Simon Sheppard
Posts: 190
Joined: 2021-Jul-10, 7:46 pm
Contact:

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by Simon Sheppard »

In your second script you have
call if %x% equ 1 (

call if is not supported (nor is CALL FOR, see https://ss64.com/nt/call.html )

If you remove the CALL then it works as expected.
Rekrul
Posts: 52
Joined: 2021-Aug-15, 11:29 pm

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by Rekrul »

Simon Sheppard wrote: 2023-Mar-01, 3:49 pm In your second script you have
call if %x% equ 1 (

call if is not supported (nor is CALL FOR, see https://ss64.com/nt/call.html )
I wasn't sure, I was just trying things I thought might work.
Simon Sheppard wrote: 2023-Mar-01, 3:49 pm If you remove the CALL then it works as expected.
Not quite. If you remove call from the second example, it becomes functionally identical to the first example, only differing in the initial value of %x%, which as the first example demonstrates, doesn't work properly if the comparison is true.

Try this;

Code: Select all

@echo off

set x=2
set test=Hello
if %x% equ 1 (
set test=Hi
set test=%test% There
)
echo %test%

set x=1
set test=Hello
if %x% equ 1 (
set test=Hi
set test=%test% There
)
echo %test%
What I would expect the output to be;

Hello
Hi There


What I get;

Hello
Hello There


When the comparison is true, the line set test=Hi never gets executed. I assume this is some flakiness due to Delayed Expansion, I was just wondering if there's some work around, other than putting the set commands in a separate routine and using a conditional call to that routine.
User avatar
Simon Sheppard
Posts: 190
Joined: 2021-Jul-10, 7:46 pm
Contact:

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by Simon Sheppard »

Hello
Hello There

Is exactly what i would expect to get because you are not using delayed expansion, so everything within the brackets is treated like a single line as far as variable expansion goes. You can SET variables, but reading them will get the value as evaluated at the start of the code block.

A good way to debug this kind of thing is to add some additional echo statements within the code block so you can see what the values are at every stage.
Echo x=[%x%] test=[%test%]
OJBakker
Posts: 13
Joined: 2021-Jul-29, 7:06 am

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by OJBakker »

If you do not use delayed expansion and you are within a code block use 'call set' to use the updated value of a variable changed within the code block.

Code: Select all

@echo off

set x=2
set test=Hello
if %x% equ 1 (
set test=Hi
call set test=%%test%% There
)
echo %test%

set x=1
set test=Hello
if %x% equ 1 (
set test=Hi
call set test=%%test%% There
)
echo %test%
pause
The same with debug-view added

Code: Select all

@echo off

set x=2
set x
set test=Hello
if %x% equ 1 (
call echo dbgEcho in a code block with call: variable=[test] pre-codeblock value=[%test%] current value=[%%test%%]
set test=Hi
call echo dbgEcho in a code block with call: variable=[test] pre-codeblock value=[%test%] current value=[%%test%%]
call set test=%%test%% There
call echo dbgEcho in a code block with call: variable=[test] pre-codeblock value=[%test%] current value=[%%test%%]
)
echo %test%

set x=1
set x
set test=Hello
if %x% equ 1 (
call echo dbgEcho in a code block with call: variable=[test] pre-codeblock value=[%test%] current value=[%%test%%]
set test=Hi
call echo dbgEcho in a code block with call: variable=[test] pre-codeblock value=[%test%] current value=[%%test%%]
call set test=%%test%% There
call echo dbgEcho in a code block with call: variable=[test] pre-codeblock value=[%test%] current value=[%%test%%]
)
echo %test%
pause
The same but using a subroutine for the debug-view.

Code: Select all

@echo off

set x=2
set x
set test=Hello
if %x% equ 1 (
call :dbgEchoByCallEcho "test" "%test%"
set test=Hi
call :dbgEchoByCallEcho "test" "%test%"
call set test=%%test%% There
call :dbgEchoByCallEcho "test" "%test%"
)
echo %test%

set x=1
set x
set test=Hello
if %x% equ 1 (
call :dbgEchoByCallEcho "test" "%test%"
set test=Hi
call :dbgEchoByCallEcho "test" "%test%"
call set test=%%test%% There
call :dbgEchoByCallEcho "test" "%test%"
)
echo %test%
pause

exit /b

:dbgEchoByCallEcho
rem parameters are : "variablename" "variablevalue"
if defined %~1 call echo dbgEchoByCallEcho variable=[%~1] pre-codeblock value=[%~2] current value=[%%%~1%%]
if not defined %~1 call echo dbgEchoByCallEcho UNDEFINED variable=[%~1] pre-codeblock value=[%~2] current value=[]
exit/b
mooring
Posts: 2
Joined: 2023-Mar-06, 9:47 am

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by mooring »

read this book
https://archive.org/details/windowsntsh ... ew=theater
"Windows NT Shell Scripting" at page 76, you will get why

before if command execute, all variables in conditioin and commands in parenthesis are substituted by their value, so the first set in if command will not work

you can use call procedure to setup the variable because variable will be reevaluated each time


ntshell.jpg
ntshell.jpg (121.27 KiB) Viewed 7107 times
Rekrul
Posts: 52
Joined: 2021-Aug-15, 11:29 pm

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by Rekrul »

OJBakker wrote: 2023-Mar-05, 3:02 pm If you do not use delayed expansion and you are within a code block use 'call set' to use the updated value of a variable changed within the code block.
Damn, I thought I had tried that. Then again, I swear sometimes that something that doesn't work one day, will work the next.

Thanks.
mooring wrote: 2023-Mar-06, 10:05 am read this book
https://archive.org/details/windowsntsh ... ew=theater
"Windows NT Shell Scripting" at page 76, you will get why
Thanks for the link. I mostly knew why it was happening, I just wasn't having any luck figuring out how to get around it.
mooring
Posts: 2
Joined: 2023-Mar-06, 9:47 am

Re: Is there any way to modify a variable twice in the same IF comparison?

Post by mooring »

here is the working copy using procedure call

Code: Select all

@echo off
set /a x=1
set test=hello
if %x% equ 1 (
    set test=
    call :setupText Hi
    call :setupText There, this works
)
echo %test%
goto :EOF
:setupText
set test=%test% %*
goto :EOF
Attachments
dblset.png
dblset.png (43.45 KiB) Viewed 7081 times
Post Reply