what rem and if (and may be for) have against pipes?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: what rem and if (and may be for) have against pipes?

#16 Post by einstein1969 » 22 Apr 2014 18:20

Hi,

I don't know how the parser work :twisted: , but why the caret before the variable name?
What mean?

Code: Select all

%^cmdcmdline%


and why this work too?

Code: Select all

echo pipe | echo ^%cmdcmdline^%

is the same?


einstein1969

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

Re: what rem and if (and may be for) have against pipes?

#17 Post by jeb » 23 Apr 2014 00:11

einstein1969 wrote:but why the caret before the variable name?


This is the method for double expanding a percent expression, but only when the expression is parsed by the cmd-line parser.

The same effect for the batch-line parser

Code: Select all

echo %%cmdcmdline%%


Why it works in the cmd-line parser?

It works as the cmd-line parser don't remove undefined variables when they are expanded.

Code: Select all

echo %ThisIsUndefined%

But in this case cmdcmdline is defined, but I don't want to so the expansion from the first cmd.exe instance,
I want to see the expansion when the pipe instance is running.

So you put one or more carets somewhere into the variablename, then the parser will first try to expand this variable, but there doesn't exists a variable with carets here.
So the expression will be unchanged, but then in the next phase the carets are removed, that's all.

jeb

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: what rem and if (and may be for) have against pipes?

#18 Post by npocmaka_ » 23 Apr 2014 01:00

jeb wrote:Hi,

sorry I'm a little bit late for this discussion :)

But I only want to show the simple cause for the strange behaviour.

Code: Select all

C:\>echo pipe | if defined X lss Y echo %^cmdcmdline%

Output wrote:C:\Windows\system32\cmd.exe /S /D /c" if definedX lss Y echo %cmdcmdline% "

As you can see the two tokens just behind the IF are simply combined into one :idea:

Sometimes it can help when you see how the parser restructure the line... :D

jeb


Woow wow wow. :shock: Nice trick with the cmdcmdline. And is right in time :D Thanks Jeb.
Now it's almost clear what's going on.
But rather the tokens before the first comparable/examined item are swallowed rather right after if;

Code: Select all

>echo pipe|if not /i gtr GTR lss  echo %^cmdcmdline%
C:\WINDOWS\system32\cmd.exe /S /D /c" if not /iGTR GTR lss  echo %cmdcmdline%"



And If command is parsed twice.Once before piping , and for the second time after the pipe when (all) the delimiter tokens are swallowed.


And any idea what happens here :?: :

Code: Select all

echo pipe|if not gtr GTR lss  echo %^cmdcmdline%


Looks like cmdcmdline cannot be expanded?

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: what rem and if (and may be for) have against pipes?

#19 Post by penpen » 23 Apr 2014 03:13

npocmaka_ wrote:And any idea what happens here :?: :

Code: Select all

echo pipe|if not gtr GTR lss  echo %^cmdcmdline%


Looks like cmdcmdline cannot be expanded?
No, it is just an endless loop ("gtrGTR < echo"); cmdcmdline is expanded to:
C:\WINDOWS\system32\cmd.exe /S /D /c" if not gtrGTR lss echo %cmdcmdline%"


penpen

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: what rem and if (and may be for) have against pipes?

#20 Post by penpen » 23 Apr 2014 03:20

You may get the /I switch to work by using it right after if:

Code: Select all

C:\>echo pipe|if /I not 0 lss neq 0lss  echo %^cmdcmdline%
C:\WINDOWS\system32\cmd.exe /S /D /c" if /I not 0LSS neq 0lss  echo %cmdcmdline%"

C:\>echo pipe|if /I 0 lss equ 0lss  echo %^cmdcmdline%
C:\WINDOWS\system32\cmd.exe /S /D /c" if /I 0LSS equ 0lss  echo %cmdcmdline%"

C:\>


penpen

Edit: Replaced the examples by more meaningfull ones (where /I is indeed needed...).

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: what rem and if (and may be for) have against pipes?

#21 Post by dbenham » 23 Apr 2014 05:24

You can get an IF statement to work normally if you insert an extra layer of CMD /C.

Code: Select all

echo pipe | cmd /c "if 1 lss 2 more"


Dave Benham

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

Re: what rem and if (and may be for) have against pipes?

#22 Post by jeb » 23 Apr 2014 15:42

dbenham wrote:You can get an IF statement to work normally if you insert an extra layer of CMD /C.

Ok, but that will start one more CMD.exe instance.

But there exists an even more simple solution with double expansion

Code: Select all

@echo off
set "myLine=if 1 lss 2 more"
echo pipe | ( %%myLine%%)

Take notice of the parenthesis around the command :!:
Without the parenthesis you get an error message, that the command %myLine% can't be found.

jeb

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: what rem and if (and may be for) have against pipes?

#23 Post by dbenham » 23 Apr 2014 16:22

jeb wrote:
dbenham wrote:You can get an IF statement to work normally if you insert an extra layer of CMD /C.

Ok, but that will start one more CMD.exe instance.

But there exists an even more simple solution with double expansion

Code: Select all

@echo off
set "myLine=if 1 lss 2 more"
echo pipe | ( %%myLine%%)

Take notice of the parenthesis around the command :!:
Without the parenthesis you get an error message, that the command %myLine% can't be found.

jeb

Very nice :!: :D

I made many attempts with double expansion, some even with parentheses, but never found a combination that worked :evil: Your working solution is much simpler than all my failed attempts :mrgreen: :lol:


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: what rem and if (and may be for) have against pipes?

#24 Post by npocmaka_ » 21 Apr 2016 05:18

Here the stackoverflow user enjoying has found another way to workaround the issue :

Code: Select all

break|if 125^  gtr 124 echo %^cmdcmdline%


Escape and two spaces.It works without pipes too - I'll test this with more complex lines with brackets and else cases...

using the example from the stackoverflow question:

Code: Select all

@echo off
for /l %%# in (0,1,9) do (
  if %%#^  equ 0 (
     echo NULL
  ) else (
     echo %%#
  )
   
)|sort   


Works fine.

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: what rem and if (and may be for) have against pipes?

#25 Post by npocmaka_ » 21 Apr 2016 05:39

One strange thing.
Originally the bug with the swallowed space occurs when the IF is on the right side of the pipe.
but when the if expression is put in brackets it occurs also in the left side:

Code: Select all

(if a equ a echo #)|more

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: what rem and if (and may be for) have against pipes?

#26 Post by npocmaka_ » 21 Apr 2016 07:40

And looks like this workaround works only for comparisons. I cant use it for If defined,If exist,...


Code: Select all

break|if defined^  cd echo %cmd^cmdline%


May this is something related to this bug.

This is also pretty strange:

Code: Select all

>set z=1
>break|if defined^  z echo #
z was unexpected at this time.
>set neq=1
>break|if defined^  neq  echo #
#


this just looks like defined,errorlevel,exist,CMDEXTVERSION are with higher prio than comparison , but comparison is with higher prio during parsing :?:

Post Reply