For example, running test.bat: -
::test.bat
@echo off & set VAL=10& set Z=VAL
echo %Z%
echo %%Z%%
echo %%%Z%%%
echo %%%%Z%%%%
echo %%%%%Z%%%%%
call echo %Z%
call echo %%Z%%
call echo %%%Z%%%
call echo %%%%Z%%%%
call echo %%%%%Z%%%%%
gives the following output (only the line 'call echo %%%Z%%%' gives me what
I originally wanted): -
VAL
%Z%
%VAL%
%%Z%%
%%VAL%%
VAL
VAL
10
%Z%
%VAL%
And running the echo commands from test.bat at the command prompt gives: -
VAL
%VAL%
%%VAL%%
%%%VAL%%%
%%%%VAL%%%%
VAL
10
%10%
%%10%%
%%%10%%%
My observations and questions: -
* The only consistent result was when referencing %Z% which always gave VAL.
* The lines 'call echo %Z%' and 'call echo %%Z%%' from test.bat both give
VAL. How on earth can those two different lines be equivalent?
* A clear pattern was forming using 'echo' (without the 'call') from the
command prompt.
* The results from the 'echo' (without the 'call') in test.bat alternate
between Z and VAL (if you ignore the %'s for the moment). How is that
happening and why does it not happen when the commands are run from the
command prompt?
* Commands run from test.bat strip away the same or more pairs of %'s than
commands run the command prompt, but never less. Why is that?
* Variable expansion seems less than scientific.
Your comments/thoughts/answers will be most welcome, Ritchie.
^ Whilst trying to obtain the value of a variable by using another variable
^ whose value was the name of the variable whose value I wanted obtain
(still
^ with me?).
I was hoping that someone else would tackle this but I guess they're all on
vacation.
^ @echo off & set VAL=10& set Z=VAL
^ echo %%%%%Z%%%%%
The percent sign is used to indicate a variable -- a string which is to be
replaced by another string. To use a percent sign as text it must be
escaped with a percent sign (%% is replaced with %). The command
interpreter (CMD.EXE) does as much of this that it can to the command line
before starting the new process. So your above command line gets modified
similar to this (spaces for readability):
echo %% %% %Z% %% %%
echo %% %% VAL %% %%
echo % % VAL % %
echo %%VAL%%
^ call echo %%%%%Z%%%%%
With CALL, the command line gets read and modified twice. It gets modified
as in my preceding example when first read by CMD.EXE. Then CALL sends it
back to CMD.EXE and it gets modified again:
CALL echo %% %% %Z% %% %%
CALL echo %% %% VAL %% %%
CALL echo % % VAL % %
CALL echo %%VAL%%
echo %%VAL%%
echo %VAL%
Note that the result is ideally suited for an additional invocation of CALL
to replace %VAL% with its value:
CALL CALL echo %% %% %Z% %% %%
CALL CALL echo %% %% VAL %% %%
CALL CALL echo % % VAL % %
CALL CALL echo %%VAL%%
CALL echo %%VAL%%
CALL echo %VAL%
echo 10
^ How on earth can those two different lines be equivalent?
Magic.
^ How is that happening and why does it not happen when the commands are
^ run from the command prompt?
CMD is in a different mode and does not use the same rules. I don't know
why MS does it this way.
^ * Variable expansion seems less than scientific.
That statement can be generalized to include CMD.EXE.
Frank
Its a dirty job, but someones got to do it :)
>
>
> ^ @echo off & set VAL=10& set Z=VAL
>
> ^ echo %%%%%Z%%%%%
>
> The percent sign is used to indicate a variable -- a string which is to be
> replaced by another string. To use a percent sign as text it must be
> escaped with a percent sign (%% is replaced with %). The command
> interpreter (CMD.EXE) does as much of this that it can to the command line
> before starting the new process. So your above command line gets modified
> similar to this (spaces for readability):
This was a great help to me, as I kind of overlooked occurences of '%%'
being
replaced with '%'
>
> echo %% %% %Z% %% %%
> echo %% %% VAL %% %%
> echo % % VAL % %
> echo %%VAL%%
>
>
> ^ call echo %%%%%Z%%%%%
>
> With CALL, the command line gets read and modified twice. It gets modified
> as in my preceding example when first read by CMD.EXE. Then CALL sends it
> back to CMD.EXE and it gets modified again:
>
This completed my understanding of what was going on, cheers!
> CALL echo %% %% %Z% %% %%
> CALL echo %% %% VAL %% %%
> CALL echo % % VAL % %
> CALL echo %%VAL%%
> echo %%VAL%%
> echo %VAL%
>
> Note that the result is ideally suited for an additional invocation of
CALL
> to replace %VAL% with its value:
>
> CALL CALL echo %% %% %Z% %% %%
> CALL CALL echo %% %% VAL %% %%
> CALL CALL echo % % VAL % %
> CALL CALL echo %%VAL%%
> CALL echo %%VAL%%
> CALL echo %VAL%
> echo 10
>
>
> ^ How on earth can those two different lines be equivalent?
>
> Magic.
Not anymore!!!
>
> ^ How is that happening and why does it not happen when the commands are
> ^ run from the command prompt?
>
> CMD is in a different mode and does not use the same rules. I don't know
> why MS does it this way.
>
> ^ * Variable expansion seems less than scientific.
>
> That statement can be generalized to include CMD.EXE.
And FINDSTR.EXE IMHO
>
> Frank
>
Thanks Frank. I now see how CMD.EXE goes about expanding variables and after
further experimentation, dare I say, I believe the process can be summarized
as below: -
--- Rules for commands entered at the prompt ---
* Rule 1. Working from left to right, expand variables ONLY if they have
been defined.
* Rule 2. Repeat Rule 1 for every 'call'.
Examples (for the examples, assume VAL=10 and Z=VAL)
* In the line 'echo %%Z%%', '%Z%' is expanded to VAL, the result is 'echo
%VAL%'
(if Z had not been defined the result would have been 'echo %%Z%%', ie no
change).
* In the line 'call echo %%Z%%', '%Z%' is expanded to VAL, the result is
'call echo %VAL%'
Then due to Rule 2, Rule 1 is repeated so 'call echo %VAL%' becomes 'echo
10'
--- Rules for Batch Files ---
* Rule 1.Working from left to right perform the following in order: -
a) replace '%%' with '%'
b) expand variables applying Rule 1a and Rule 1b
c) discard any leftover '%'
* Rule 2. Repeat Rule 1 for every 'call'.
Examples (for the examples, assume VAL=10 and Z=VAL)
* In the line 'echo %%Z%%', both occurences of '%%' are replaced by '%'
because of Rule 1a, the result is 'echo %Z%'
* In the line 'echo %%%Z%%%', the first '%%' is replaced by '%' because of
Rule 1a, then '%Z%' is expanded to 'VAL' because of Rule 1b, then the second
'%%' is replaced with '%' because of Rule 1a. The result is 'echo %VAL%'
* In the line 'call echo %%%Z%%%%', the first '%%' is replaced by '%'
because of Rule 1a, then '%Z%' is expanded to 'VAL' because of Rule 1b, then
the second and third '%%' is replaced with '%' because of Rule 1a. The
result is 'call echo %VAL%%'. Then because of Rule 2, Rule 1 is repeated so
the line becomes 'echo 10%'. Then because of Rule 1c, the leftover '%' is
discarded. The final result is 'echo 10'.
The rules also explain why the lines 'call echo %Z%' and 'call echo %%Z%%'
both evaluate to 'VAL' (when run from a batch file) and why the output from
the following lines alternates between 'VAL' and 'Z' (if you ignore the '%'
for a moment)
echo %Z% => VAL
echo %%Z%% => %Z%
echo %%%Z%%% => %VAL%
echo %%%%Z%%%% => %%Z%%
echo %%%%%Z%%%%% => %%VAL%%
I've worked through many examples and haven't found an exception to the
rules so far, anyone?
Can these rules be simplified further (assuming they're correct of course)?
Ritchie
^ --- Rules for commands entered at the prompt ---
^ --- Rules for Batch Files ---
Thank you very much for your analysis. I haven't done one -- my explanation
was only from a recollection of the behavior -- and your work may save me
some in the future.
Frank