Strange behavior in delayed expansion in FOR set

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Strange behavior in delayed expansion in FOR set

#1 Post by Aacini » 11 Nov 2012 22:10

Hi. I have a segment of code that process file names in a FOR loop and split parts of name separated by underscore, to take the first and last parts:

Code: Select all

for %%a in (*.*) do (
   set fileName=%%a
   set firstPart=
   for %%b in (!fileName:_= !) do (
      if not defined firstPart (
         set firstPart=%%b
      ) else (
         set lastPart=%%b
      )
   )
   rem Process the parts here...
)
Previous code does not work: it assigns "fileName:_" to firstPart and an empty string to lastPart (or leave it unmodified). However, if I achieve the replacement of underscores by spaces before the FOR, the code works correctly:

Code: Select all

for %%a in (*.*) do (
   set fileName=%%a
   set fileName=!fileName:_= !
   set firstPart=
   for %%b in (!fileName!) do (
      if not defined firstPart (
         set firstPart=%%b
      ) else (
         set lastPart=%%b
      )
   )
   rem Process the parts here...
)
I don't see any operative difference between a delayed expansion with replacement and a pure delayed expansion, but the first one does not work in the set of FOR command and the second one does!

What is happening here? Thanks a lot...

Antonio

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

Re: Strange behavior in delayed expansion in FOR set

#2 Post by dbenham » 11 Nov 2012 22:39

The FOR command gets special parsing, which requires that the = in delayed search and replace must be either escaped or quoted. In this case quotes will interfere with the functionality, so it needs to be escaped. IF statements with delayed search and replace have the same issue.

Code: Select all

for %%a in (*.*) do (
   set fileName=%%a
   set firstPart=
   for %%b in (!fileName:_^= !) do (
      if not defined firstPart (
         set firstPart=%%b
      ) else (
         set lastPart=%%b
      )
   )
   rem Process the parts here...
)


Dave Benham

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

Re: Strange behavior in delayed expansion in FOR set

#3 Post by jeb » 12 Nov 2012 08:03

Only a small additional rematk to Dave's answer.

It's only necessary to escape when using delayed expansion, with percent expansion escaping is not necessary,
it would even break the code.

It's all a matter of the time when the expression will be parsed.
The percent expression is parsed before the special parser of "FOR" or "IF" sees the line.
Delayed expansion will be evaluated after the special parser, this is also the cause why it's not possible to set options for "FOR" or "IF" with delayed expansion.

Code: Select all

setlocal EnableDelayedExpansion
set option1=/F
set option2=/I
FOR !option1! ...  fails
IF !option2! ... fails

But these works

Code: Select all

set option1=/F
set option2=/I
FOR %option1% "delims=" %%A  ...
IF %option2% a==A


jeb

Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Strange behavior in delayed expansion in FOR set

#4 Post by Aacini » 12 Nov 2012 17:25

Dave, jeb: Thanks a lot! :) :D (again :mrgreen: )

Antonio

Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Strange behavior in delayed expansion in FOR set

#5 Post by Aacini » 13 Nov 2012 21:35

I just have realized that the same behavior happens with comma character (in a program at this site):

Code: Select all

   for %%b in (X!line:^,^= X!) do (
I suppose that the same behavior will happen with semicolon (the three standard Batch separators for parameters and FOR sets), but I have not time right now to do some tests...

Antonio

Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Strange behavior in delayed expansion in FOR set

#6 Post by Aacini » 12 Dec 2012 21:11

jeb wrote:It's all a matter of the time when the expression will be parsed.
The percent expression is parsed before the special parser of "FOR" or "IF" sees the line.
Delayed expansion will be evaluated after the special parser, this is also the cause why it's not possible to set options for "FOR" or "IF" with delayed expansion.

Code: Select all

setlocal EnableDelayedExpansion
set option1=/F
set option2=/I
FOR !option1! ...  fails
IF !option2! ... fails

But these works

Code: Select all

set option1=/F
set option2=/I
FOR %option1% "delims=" %%A  ...
IF %option2% a==A


jeb

I need to execute this:

Code: Select all

set recPath=AnyValueWithNoSpaces
for /R !recPath! %%a in (*.*) do ...
but it not works. Is the [path] part of FOR /R path parsed as option by the parser?

I tried this way:

Code: Select all

for %%r in (!recPath!) do for /R %%r %%a in (*.*) do ...
But don't works either; however, in this case the error message is: "%a was unexpected at this time." I think that the parser should know that %%r belongs to the first FOR (with future !recPath! value), so it should correctly match %%a with the second FOR. What happens here?

A possible solution is this:

Code: Select all

cd !recPath!
for /R %%a in (*.*) do ...
but I don't like it.

Is there any way to directly execute this? Thanks...

Antonio

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

Re: Strange behavior in delayed expansion in FOR set

#7 Post by dbenham » 12 Dec 2012 22:10

Nope, can't do it. Jeb already stated as much
jeb wrote:Delayed expansion will be evaluated after the special parser, this is also the cause why it's not possible to set options for "FOR" or "IF" with delayed expansion.

The same is true for FOR variables. Only normal expansion can be used with FOR and IF options.

Again, it is the timing. CMD.EXE parses FOR and IF options prior to FOR variable expansion (which is also prior to delayed expansion).

Dave Benham

Post Reply