Unbalanced parentheses in variable expansion

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,856
48
Albuquerque, NM
prospero.unm.edu
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.
 
Aug 2, 2011
258
4
Berlin, Germany
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
11,021
98
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.
 
May 20, 2008
9,445
63
Syracuse, NY, USA
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
11,021
98
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.)
 
May 20, 2008
9,445
63
Syracuse, NY, USA
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
 
May 20, 2008
9,445
63
Syracuse, NY, USA
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?