The main content discussed in this post is closely related to delayed expansion. Beginners are advised to first refer to the following links:
Detailed explanation of delayed expansion
http://www.cn-dos.net/forum/viewthread.php?tid=28273
When should delayed expansion be used
http://www.cn-dos.net/forum/viewthread.php?tid=20733
A problem of a variable nested inside a variable
http://www.cn-dos.net/forum/viewthread.php?tid=41143
Enough nonsense, straight to the point:
First, here's one of my test p's:
for /l %%j in (1,1,10) do (
set x=%%Down%%j%%
pause
)
Don't unnecessarily add @echo off, otherwise you won't be able to see the execution process
I added a pause with the intention of analyzing only the first loop (there are ten in total; if you don't add it, you're responsible for the consequences
)
After execution and analysis, you'll find that for gets split into two "statements" for execution
++++++++++++++++++
for /l %j in (1,1,80) do (
set x=%Down%j%
pause
)
++++++++++++++++++
(
set x=%Down1%
pause
)
++++++++++++++++++
(If you don't understand the description above, please run p yourself and look at the result)
According to the principle of delayed expansion, that is, the cmd preprocessing mechanism, cmd preprocesses every statement it reads, and anything with %% will be expanded (unless you turn off cmd expansion). Here's an off-topic example to help everyone understand:
set a=1234567890abcdefg
set b=4
set c=5
echo %%a:~%b%,%c%%%
call echo %%a:~%b%,%c%%%
pause
This kind of code is often used to scare newbies. Actually there is a more concise way (that's right, using !!, work out the specific implementation yourself). In fact, there are still rules to follow. Don't blink, watch the cmd preprocessing steps:
When cmd reads the line echo %%a:~%b%,%c%%% (hmph, wearing so many %% to look tough? Strip them!
)
After stripping, it becomes echo %a:~4,5%
(%% gets stripped to %, while %b% and %c% are only wearing one layer of %%, so after stripping they show their true form
)
So the result of echo %%a:~%b%,%c%%% is %a:~4,5%. You may ask, isn't %a:~4,5% a standard variable reference? Why isn't the result 56789? Let me keep you in suspense for a moment, and keep reading the next line call echo %%a:~%b%,%c%%%. Those with experience, don't just sit there, hurry up and strip it!
call echo %a:~4,5%,not too different from the previous line, just one extra call. Hehe, now you know why I kept you in suspense, right? The result of this line is exactly 56789, because the role of call is to strip one more layer. After stripping %% you get the result you really wanted.
Back to the main topic, I guess
for /l %%j in (1,1,10) do (
set x=%%Down%%j%%
pause
)
after stripping, becomes:
for /l %j in (1,1,80) do (
set x=%Down%j%
pause
)
and then after stripping again, becomes:
(
set x=%Down1%
pause
)
Stop! Look here. Doesn't this feel a bit strange? No matter how hard you look, all you can see is the assignment relation %j=1, right?
Yes, that's also my current guess: the second statement does not have any "stripping" event; it is purely an assignment action. Everyone can add %% to verify the result.
My conclusion is: for is first preprocessed by cmd, stripping off one layer of %%, and the subsequent loop only performs assignment, without any further "stripping" behavior. If you want more "stripping", add call or setlocal yourself!!
PS: Since I'm rather lazy, the for statement example was taken from http://www.cn-dos.net/forum/viewthread.php?tid=24418. This is a great learning example and gave me quite a few ideas and inspirations
[ Last edited by maky1117 on 2008-11-24 at 19:42 ]
Detailed explanation of delayed expansion
http://www.cn-dos.net/forum/viewthread.php?tid=28273
When should delayed expansion be used
http://www.cn-dos.net/forum/viewthread.php?tid=20733
A problem of a variable nested inside a variable
http://www.cn-dos.net/forum/viewthread.php?tid=41143
Enough nonsense, straight to the point:
First, here's one of my test p's:
for /l %%j in (1,1,10) do (
set x=%%Down%%j%%
pause
)
Don't unnecessarily add @echo off, otherwise you won't be able to see the execution process

I added a pause with the intention of analyzing only the first loop (there are ten in total; if you don't add it, you're responsible for the consequences
)After execution and analysis, you'll find that for gets split into two "statements" for execution
++++++++++++++++++
for /l %j in (1,1,80) do (
set x=%Down%j%
pause
)
++++++++++++++++++
(
set x=%Down1%
pause
)
++++++++++++++++++
(If you don't understand the description above, please run p yourself and look at the result)
According to the principle of delayed expansion, that is, the cmd preprocessing mechanism, cmd preprocesses every statement it reads, and anything with %% will be expanded (unless you turn off cmd expansion). Here's an off-topic example to help everyone understand:
set a=1234567890abcdefg
set b=4
set c=5
echo %%a:~%b%,%c%%%
call echo %%a:~%b%,%c%%%
pause
This kind of code is often used to scare newbies. Actually there is a more concise way (that's right, using !!, work out the specific implementation yourself). In fact, there are still rules to follow. Don't blink, watch the cmd preprocessing steps:
When cmd reads the line echo %%a:~%b%,%c%%% (hmph, wearing so many %% to look tough? Strip them!
)After stripping, it becomes echo %a:~4,5%
(%% gets stripped to %, while %b% and %c% are only wearing one layer of %%, so after stripping they show their true form
)So the result of echo %%a:~%b%,%c%%% is %a:~4,5%. You may ask, isn't %a:~4,5% a standard variable reference? Why isn't the result 56789? Let me keep you in suspense for a moment, and keep reading the next line call echo %%a:~%b%,%c%%%. Those with experience, don't just sit there, hurry up and strip it!
call echo %a:~4,5%,not too different from the previous line, just one extra call. Hehe, now you know why I kept you in suspense, right? The result of this line is exactly 56789, because the role of call is to strip one more layer. After stripping %% you get the result you really wanted.
Back to the main topic, I guess
for /l %%j in (1,1,10) do (
set x=%%Down%%j%%
pause
)
after stripping, becomes:
for /l %j in (1,1,80) do (
set x=%Down%j%
pause
)
and then after stripping again, becomes:
(
set x=%Down1%
pause
)
Stop! Look here. Doesn't this feel a bit strange? No matter how hard you look, all you can see is the assignment relation %j=1, right?
Yes, that's also my current guess: the second statement does not have any "stripping" event; it is purely an assignment action. Everyone can add %% to verify the result.My conclusion is: for is first preprocessed by cmd, stripping off one layer of %%, and the subsequent loop only performs assignment, without any further "stripping" behavior. If you want more "stripping", add call or setlocal yourself!!
PS: Since I'm rather lazy, the for statement example was taken from http://www.cn-dos.net/forum/viewthread.php?tid=24418. This is a great learning example and gave me quite a few ideas and inspirations

[ Last edited by maky1117 on 2008-11-24 at 19:42 ]

