Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Unexpected result from a pair of IF statements

51 views
Skip to first unread message

jgq...@gmail.com

unread,
Sep 16, 2016, 5:43:36 AM9/16/16
to
I have always assumed that I could combine together IF statements in the form
(IF condition1) AND (IF condition2)
THEN both condition1 and condition2 are true
ELSE one or both of condition1 and condition2 are false
until I came across the following problem, which I demonstrate using the code

@echo off
:: check behaviour of IF statements on same line
setlocal enabledelayedexpansion
for /l %%a in (1,1,7) do (
echo.&echo number set to %%a
if %%a geq 3 if %%a leq 5 (
echo number is 3, 4 or 5
) else (
echo number is less than 3 or greater than 5
)
)
endlocal
pause

This gives the result:

number set to 1

number set to 2

number set to 3
number is 3, 4 or 5

number set to 4
number is 3, 4 or 5

number set to 5
number is 3, 4 or 5

number set to 6
number is less than 3 or greater than 5

number set to 7
number is less than 3 or greater than 5

I get no message at all for values 1 and 2, whereas in each case I would expect
number is less than 3 or greater than 5

Have I been missing something fundamental for the last couple of decades?

JJ

unread,
Sep 16, 2016, 8:22:41 AM9/16/16
to
Any internal and external commands have this very simple syntax:

{command}, then optional [parameters...]

In IF command, the "IF" is the command, and *any* text following it, is its
parameters. Thus, the "%%a geq 3 if %%a leq 5..." is the whole parameters of
the first IF command.

In the first IF context, its condition parameter is "%%a geq 3", and its
conditional command parameter is the second IF, which is "if %%a leq 5
(echo...". All text following the second IF, which is "%%a leq 5 (echo...",
is the whole parameters for the second IF. i.e. the conditional command's
parameters of the first IF.

So, your code is actually interpreted like this:

if %%a geq 3 (
if %%a leq 5 (
echo number is 3, 4 or 5
) else (
echo number is less than 3 or greater than 5
)
)

To achieve what you wanted, you'll need to provide commands for both true
and false result of the IF condition. i.e.

if %%a geq 3 (
if %%a leq 5 (
echo number is 3, 4 or 5
) else (
echo number is less than 3 or greater than 5
)
) else (
echo number is less than 3 or greater than 5
)

To understand complex IF commands or grouped commands, format the code in a
hierarchical manner like above, and insert an opening command group each
time a command parameter is a subcommand. e.g.

if %%A==1 for /l %%C in (1,1,3) do if %%C==2 if %%B==3 echo abc&echo xyz

Is actually...

if %%A==1 (
for /l %%C in (1,1,3) do (
if %%C==2 (
if %%B==3 (
echo abc
echo xyz
)
)
)
)

To avoid confusion when building multiple IF commands, always use command
grouping on all conditional commands of each IF command. Only after you've
ensured that it has worked the way you wanted, you can safely remove any
unnecessary command grouping. This also applies to other command which
requires subcommand such as FOR. e.g.

if %%A==0 ( if %%B==0 ( echo abc ) )
for %%A in (a b c) do ( echo %%A )

John Gray

unread,
Sep 17, 2016, 1:15:12 PM9/17/16
to
Thank you!

I thought I had understood what you had written, but I took your example and modified it to test two passed parameters to a subroutine, as follows:

@echo off

for %%a in (t f) do (
for %%b in (t f) do (
call :ifif %%a %%b
)
)
goto :eof

:ifif
if "%1"=="t" (
if "%2"=="t" (
echo #1 %%1 is %1 %%2 is %2
) else (
echo #2 %%1 is %1 %%2 is %2
)
) else (
echo #3 %%1 is %1 %%2 is %2
)
goto :eof

The results were:
#1 %1 is t %2 is t
#2 %1 is t %2 is f
#3 %1 is f %2 is t
#3 %1 is f %2 is f
--
At what point would I insert another echo statement
echo #4 %%1 is %1 %%2 is %2
to give the fourth option where both arguments were "f"?
I have tried for about an hour without success.

And secondly, please could you show me how to write the code for my original wish, namely
(IF condition1) AND (IF condition2)
THEN both condition1 and condition2 are true
ELSE one or both of condition1 and condition2 are false

perhaps using my true/false example?
Thanks again!

JJ

unread,
Sep 18, 2016, 2:39:49 AM9/18/16
to
Your parentheses are incomplete.

John Gray

unread,
Sep 19, 2016, 12:33:16 PM9/19/16
to
I'm not sure what you mean by that - I've just cut and pasted from my post above into a batch file, run it, and I get the same result as I posted above.
Message has been deleted

petu...@googlemail.com

unread,
Sep 21, 2016, 3:56:54 AM9/21/16
to
echo #1 %%1 is t %%2 is t
) else (
echo #2 %%1 is t %%2 is f
)
) else (
if "%2"=="t" (
echo #3 %%1 is f %%2 is t
) else (
echo #4 %%1 is f %%2 is f
)
)
goto :eof

John Gray

unread,
Sep 21, 2016, 10:28:08 AM9/21/16
to
The only way I can get this to work successfully is as follows:

@echo off
:: call with all possible true and false parameters
call :ifif t t
call :ifif t f
call :ifif f t
call :ifif f f
pause
goto :eof

:ifif
if "%1"=="t" (
if "%2"=="t" (
echo #1 %%1 is %1 %%2 is %2 expect TT
) else (
echo #2 %%1 is %1 %%2 is %2 expect TF
)
) else (
if "%2"=="t" (
echo #3 %%1 is %1 %%2 is %2 expect FT
) else (
echo #4 %%1 is %1 %%2 is %2 expect FF
)
)
)
goto :eof

Can anyone simplify this surprisingly complex code?

Herbert Kleebauer

unread,
Sep 21, 2016, 11:58:55 AM9/21/16
to
On 16.09.2016 11:43, jgq...@gmail.com wrote:

> @echo off
> :: check behaviour of IF statements on same line
> setlocal enabledelayedexpansion
> for /l %%a in (1,1,7) do (
> echo.&echo number set to %%a
> if %%a geq 3 if %%a leq 5 (
> echo number is 3, 4 or 5
> ) else (
> echo number is less than 3 or greater than 5
> )
> )
> endlocal

You can use:

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
setlocal enabledelayedexpansion
for /l %%a in (1,1,7) do (
set /a m=(%%a-3^)*(5-%%a^)
if !m! lss 0 echo %%a is less than 3 or greater than 5
if !m! geq 0 echo %%a is 3, 4 or 5
)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


> @echo off
>
> for %%a in (t f) do (
> for %%b in (t f) do (
> call :ifif %%a %%b
> )
> )
> goto :eof
>
>:ifif
> if "%1"=="t" (
> if "%2"=="t" (
> echo #1 %%1 is %1 %%2 is %2
> ) else (
> echo #2 %%1 is %1 %%2 is %2
> )
> ) else (
> echo #3 %%1 is %1 %%2 is %2
> )
> goto :eof


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
for %%a in (t f) do (
for %%b in (t f) do (
call :ifif %%a %%b
)
)
goto :eof

:ifif
if "%1%2"=="tt" echo #1 %%1 is t % %2 is t
if "%1%2"=="tf" echo #2 %%1 is t % %2 is f
if "%1%2"=="ft" echo #3 %%1 is f % %2 is t
if "%1%2"=="ff" echo #4 %%1 is f % %2 is f
goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

John Gray

unread,
Sep 26, 2016, 4:06:13 AM9/26/16
to
Thanks, Herbert - a couple of interesting solutions!
I was moving from the particular to the general in my examples.

I note that provided one is interested ONLY in the True+True situation, then
IF condition1 IF condition2 command-for-both-true
will work as expected.

Otherwise one is in the realms of THENIF and ELSEIF, as my previous example indicates...
0 new messages