#1 22 Sep 2016 11:02

ManWithNoName
New Member
Registered: 22 Sep 2016
Posts: 4

Using pipes with IF in a for /f loop ?

Hello

I would like use pipes with IF command as defined in SS64 website but when I want to use it within a for /f command, it seems not work.
I have tried to escape the pipe one and two times, but there is no change.

Rem. : I'm using it inside a cmd file.

Sample 1 (Without escaping pipes)
for /f "tokens=*" %%s in ('command') do (
    ECHO %%s
    if (%%s == %var1% | %%s == %var2% | %%s == %var3%) (
        ECHO NO we can't !!!
        GOTO nextstep
        ) else (
        ECHO YES we can !!!
        )
    )
:nextstep

Sample 2 (With escaping pipes)
for /f "tokens=*" %%s in ('command') do (
    ECHO %%s
    if (%%s == %var1% ^| %%s == %var2% ^| %%s == %var3%) (
        ECHO NO we can't !!!
        GOTO nextstep
        ) else (
        ECHO YES we can !!!
        )
    )
:nextstep

Where is the problem ?
Is it a command line limitations ?
Is there a workaround ?

Regards

Offline

#2 22 Sep 2016 12:39

dbenham
Member
From: U.S. east coast
Registered: 15 Apr 2012
Posts: 109

Re: Using pipes with IF in a for /f loop ?

The FOR loop has no impact on the syntax of an IF statement within the DO block.

You cannot pipe multiple conditions of an IF statement, and I'm pretty sure SS64 never implies that you can.

Batch does not have any Boolean logic operators for IF statements. You can simulate AND by concatenating IF statements (but then ELSE becomes problematic).

Your logic is screwy. Both the TRUE and FALSE conditions will end up at :nextstep, with or without GOTO.

Offline

#3 22 Sep 2016 15:07

ManWithNoName
New Member
Registered: 22 Sep 2016
Posts: 4

Re: Using pipes with IF in a for /f loop ?

This example of code is not complete, this is just to illustrate the problem.
There is of course some code above the :nextstep tag, otherwise this is not usefull !!!
And in this case, the else is not necessary too, I know.

I can simplify that code example without goto :

for /f "tokens=*" %%s in ('command') do (
    ECHO %%s
    if (%%s == %var1% | %%s == %var2% | %%s == %var3%) (
        ECHO NO we can't !!!
        ) else (
        ECHO YES we can !!!
        )
    )


This is an extract of the SS64 IF webpage :

Pipes

    When piping commands, the expression is evaluated from left to right, so

    IF... | ... is equivalent to (IF ... ) | ...

    you can also use the explicit syntax IF (... | ...)

    Placing an IF command on the right hand side of a pipe is also possible but the CMD shell is buggy in this area and can swallow one of the delimiter characters causing unexpected results.
    A simple example that does work:

    Echo Y | IF red==blue del *.*

I understand with "you can also use the explicit syntax IF (... | ...)" that I can do it !!!
So where is the problem ?

Offline

#4 22 Sep 2016 15:36

dbenham
Member
From: U.S. east coast
Registered: 15 Apr 2012
Posts: 109

Re: Using pipes with IF in a for /f loop ?

OK, I see the source of confusion now. The problem is the documentation is pseudo code, which is open to interpretation, and you interpreted it in a way that was not intended.

Each side of a pipe must have a complete command, but you are attempting to put only IF conditions on either side of a pipe.

The doc left out the condition, which was why you were confused. Perhaps it will make more sense as:

if SomeCondition Command1 | Command2

which is interpreted logically as

(if SomeCondition Command1) | Command2

The result is that the pipe is always created and Command2 is always run, regardless whether SomeCondition is TRUE or FALSE

This contrasts with

if SomeCondition (Command1 | Command2)

which only creates a pipe and runs Command2 if SomeCondition is TRUE.


Dave Benham

Offline

#5 22 Sep 2016 16:25

ManWithNoName
New Member
Registered: 22 Sep 2016
Posts: 4

Re: Using pipes with IF in a for /f loop ?

OK,
Thanks for your anwser, I think I understand better now !

I thought pipes in this case could be used as an OR function as we can meet with some program languages.

My goal was to test in this way :
IF ((value1 == value2) or (value1 == value3) or (value1 == value4))

Is there a good way to do it ?

Regards

Offline

#6 22 Sep 2016 18:28

dbenham
Member
From: U.S. east coast
Registered: 15 Apr 2012
Posts: 109

Re: Using pipes with IF in a for /f loop ?

The only Boolean operator that IF supports is NOT. There is no AND, OR, XOR, etc.

The easiest way to simulate OR is via multiple IF and a temporary variable.

set "true="
if value1 == value2 set true=1
if value1 == value3 set true=1
if value1 == value4 set true=1
if defined true (
  echo TRUE
) else (
  echo FALSE
)

if case does not matter, and you don't have any `!` in the value, then you may be able to use this hack:
Assume VAR contains the value that is to be checked against a list of values:

set "var=val3"
set "list= val1 val2 val3 val4 val5 val6 "
setlocal enbledelayedExpansion
for /f "delims=" %%V in ("!var!") do if "!list: %%V =!" neq "" (
  echo TRUE
) else (
  echo FALSE
)

Dave Benham

Last edited by dbenham (22 Sep 2016 18:33)

Offline

#7 22 Sep 2016 22:39

Simon Sheppard
Super Administrator
Registered: 27 Aug 2005
Posts: 867
Website

Re: Using pipes with IF in a for /f loop ?

Thanks again Dave,
I have updated the IF page with some AND and OR examples to make this a bit clearer
http://ss64.com/nt/if.html

Offline

#8 22 Sep 2016 22:49

ManWithNoName
New Member
Registered: 22 Sep 2016
Posts: 4

Re: Using pipes with IF in a for /f loop ?

Thanks for the tips.

I'm not sure understanding very well the second example. I have tested it and it seems not work.

I wrote these code lines from your 2nd example :

@echo off
setlocal enabledelayedExpansion

rem ref value to compare
set "var="

rem list of values to compare with the reference value
set "list= val1 val2 val3 val4 val5 val6 "

goto :beg

rem functions
:test
set true=0
for %%V in (%list%) do (
	set val=%%V
	if "!val:%var%=!" equ "" set true=1		
	)
if %true% == 1 (
	ECHO TRUE
	) else (
	ECHO FALSE
	)
exit /b

rem program begining
:beg

rem ref value which is in the list
set "var=val3"
call :test

echo ------------------------

rem ref value which is not in the list
set "var=val8"	
call :test
	
pause

Offline

Board footer

Powered by FluxBB