Unbalanced parentheses in variable expansion

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,724
47
Albuquerque, NM
prospero.unm.edu
#1
I don't understand this:

Code:
C:\>set open=(test

C:\>set close=test)

C:\>echo %open %close
(test %close

C:\>
It seems that the contents of the first variable can prevent variable expansion later on the command line. Is this behavior intended? If so, is there a workaround? I've tried using %[TEST], SETDOS /X-5, SETDOS /X-7.
 
#2
simple but funny.
CMD can handle it.
Code:
(system)  C:\...\TCMD14x64 >cmd
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Alle Rechte vorbehalten.
 
(%@label[])  set open=(test
 
(%@label[])  set close=test)
 
(%@label[])  echo %open% %close%
(test test)
 

rconn

Administrator
Staff member
May 14, 2008
10,764
97
#6
It seems that the contents of the first variable can prevent variable expansion later on the command line. Is this behavior intended?
Yes.

If so, is there a workaround? I've tried using %[TEST], SETDOS /X-5, SETDOS /X-7.
Yes -- the one you didn't try (SETDOS /X-4). This behavior is due to nested variable expansion being turned off inside (potential) command groups.
 
#9
Yes.



Yes -- the one you didn't try (SETDOS /X-4). This behavior is due to nested variable expansion being turned off inside (potential) command groups.
Code:
v:\> set a=(
v:\> echo %a %a
( %a
I am having a tough time trying to understand your explanation. First, where's the nested variable? And second, if the problem is that nested variable expansion is off, how does turning nested variable expansion **OFF** fix it?
 

rconn

Administrator
Staff member
May 14, 2008
10,764
97
#10
Code:
v:\> set a=(
v:\> echo %a %a
( %a
I am having a tough time trying to understand your explanation. First, where's the nested variable? And second, if the problem is that nested variable expansion is off, how does turning nested variable expansion **OFF** fix it?
The parser passes the line through the variable expansion multiple times (until no more expansions occur). The first pass looks like:

echo ( %a

It then looks for the next variable, starting at the point of the first substitution (if nested expansion is enabled):

( %a

The parser sees that the beginning of the argument is a (, and that we do *not* want to do nested variable expansion inside a command group (or FOR argument list), so it moves the point to look for the next variable to just after the trailing ) or end of line, and the result is:

echo ( %a

By turning off nested variable expansion, the parser skips the entire length of the first expanded variable, so the second pass looks like:

%a

which is expanded to:

(

resulting in:

echo ( (

(There is no way this is going to be changed, as among other things it would break every batch file that used variables in FOR arguments.)
 
#11
I'll have to chew on that for a while.

Then why isn't the this_might_be_a_command_group mechanism triggered if I just do this?
Code:
v:\> set a=0
v:\> echo ( %a
( 0
 
#13
I'm not suggesting you change anything since I doubt I'll ever have to work around the behavior. But I'm still trying to figure it out. Can you give an example where the behavior under discussion has a positive effect?