Batch file variable with spaces and parentheses

2019-07-02 11:53发布

问题:

I've read numerous threads on different approaches to getting the windows batch file parser to properly handle variables that have spaces, parentheses, and other special characters, but none of the recommendations seems to be able to fix the issue I am having.

Here is the script (prior to trying any workarounds), whose goal is to set a value for variable03 based on the values found for variable01 and variable02:

set variable01="C:\Program Files (x86)\SomeProgram\Subfolder"
set variable02="${macro}"

set variable01=%variable01:"=%
set variable02=%variable02:"=%

set variable03=""

if %variable02:~0,1%==$ (
   if %variable01:~0,1%==$ (
      set variable03=%variable03:"=%
   ) else (
      set variable03=-o '%variable01%'
   )
)

...the values of variable01 and variable02 are not known in advance - they are substituted by another program prior to running the script, so the above script is showing an example set of values for variable01 and variable02 after that substitution has been made.

The error I get when this script runs is:

\SomeProgram\Subfolder' was unexpected at this time.

...which corresponds to the last 'set' line in the above script. I assumed that this error was due to the parentheses in the value of variable01.

If I change that line to this:

set "variable03=-o '%variable01%'"

...then I get this error:

Files was unexpected at this time.

...which seems to indicate that it is trying to tokenize on the spaces in variable01, and the parser is still not happy.

If I then add this line at the top of the script:

 setlocal enableextensions enableDelayedExpansion

...and change %variable01% to !variable01!, I still get the same error.

Clearly, I do not understand what the batch file parser needs to meet my requirement that the value of variable03 has the following value:

-o 'C:\Program Files (x86)\SomeProgram\Subfolder'

...any suggestions?

回答1:

The problem is the parentheses in variable01's value. Since it's being expanded in an if condition, those parentheses are being interpreted as flow control. Fix by always putting it in double quotes.

set variable01="C:\Program Files (x86)\SomeProgram\Subfolder"
set variable02="${macro}"

set variable01=%variable01:"=%
set variable02=%variable02:"=%

set variable03=""

if "%variable02:~0,1%"=="$" (
   if "%variable01:~0,1%"=="$" (
      set variable03=%variable03:"=%
   ) else (
      call :set3 "%variable01%"
   )
)
goto :eof

REM If it is important to have single quotes instead of double then
REM I found I had to call a subroutine.  Otherwise the set could be
REM left up in the else.
:set3
set variable03=-o '%~1'
goto :eof


回答2:

As Nate wrote, the problem in this case are the brackets, but the complete code is still unstable.

It's always better to use delayed expansion, as this is safe against any special characters.
And you should use the extended syntax of SET set "variable=content" to enclose the complete expression with quotes, then it's nearly safe, and the quotes are not added to the content.
And you don't need to remove the quotes later.

This should work with any content in var1 and var2

setlocal EnableDelayedExpansion
set "variable01=C:\Program Files (x86)\SomeProgram\Subfolder"
set "variable02=${macro}"

set "variable03="

if "!variable02:~0,1!"=="$" (
   if "!variable01:~0,1!"=="$" (
      rem
   ) else (
      set "variable03=-o '!variable01!'"
   )
)
echo(!variable03!