Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parenthesis in variables inside IF blocks

In one of my scripts, I need to use variables that contain parenthesis inside IF statements, but either the string is missing a closing parenthesis or the script exits prematurely with * was unexpected at this time (not actually an asterisk), depending on the scenario.

 

Example

@echo off

SET path=%programFiles(x86)%
echo Perfect output: %path%
IF NOT "%path%" ==  "" (
    REM Variable is defined
    echo Broken output:  %path%
)

pause >nul

Output

Perfect output: C:\Program Files (x86)
Broken output:  C:\Program Files (x86

 

I think/know that this is because it thinks the closing parenthesis in C:\Program Files (x86) is the end of the IF statement and it exits before the echo is complete.

Is there a simple way to cirumvent this? Preferably without resorting to

  1. single-line IF statements, as I need to run more than one line of code within them,
  2. copious amounts of GOTOs, as it's not practical,
  3. SETLOCAL EnableDelayedExpansion and using !path! instead of %path%, as I recall reading somewhere that that method doesn't work consistently across OSs.

If not, I'll happily accept the most reliable solution offered, whatever it is.

 

(The scenario isn't up for debate. This is just a refined, concentrated example of the problem. The structure needs to be like this, as it is in my actual script, for reasons I won't go into. It's besides the point and it'll just confuse things and distract from the actual issue.)

like image 272
mythofechelon Avatar asked Aug 14 '12 00:08

mythofechelon


People also ask

Can you put parentheses in IF statement?

You should generally use the parenthesis when you have to, and that would be when issues with operator presedence occur. @JFit OP is talking about ( ) inside the conditional expression, not { } wrapping the body of the if statement.

What goes inside of the parentheses of an if statement?

if..else statements In an if...else statement, if the code in the parenthesis of the if statement is true, the code inside its brackets is executed. But if the statement inside the parenthesis is false, all the code within the else statement's brackets is executed instead.

Do or statements need parentheses?

If you have an AND statement and a number of logically related OR statements (where the OR statements are on the same field), you should always use parentheses to group the OR statements together.


1 Answers

First off - you should never use the PATH variable for your own use. It is a reserved environment variable. Using it for your own purposes can break your scripts.

The simplest solution really is to use delayed expansion. As long as your platform uses CMD.EXE then you have access to delayed expansion.

But there is a relatively easy way to make it work without delayed expansion. You can use disappearing quotes. The quote exists at parse time as the name of a FOR variable while the command is parsed. It expands to nothing before execution time.

@echo off

SET mypath=%programFiles(x86)%
echo Perfect output: %mypath%
IF NOT "%mypath%" ==  "" (
  REM Variable is defined
  for %%^" in ("") do echo fixed output:  %%~"%mypath%%%~"
)

pause >nul

EDIT - When to use delayed expansion: Response to comment

I generally only use delayed expansion when it is needed (or more precisely, when it is advantageous). That being said, I usually find it advantageous in some portion of my batch code.

Major Advantages

  • Inside a code block in order to see changes to a variable within the block
  • When dereferencing the name of a variable. If a variable name is passed in as a parameter, the value of the variable can be gotten via delayed expansion: echo !%1!
  • When using variables as arguments to search and replace or substring operations: echo !var:%search%=%replace%!, echo !var:%start%,%len%!.
  • Whenever I need to expand the value and not worry about special characters within it needing escaping or quoting: set "var=A&B" & echo !var!

There are other methods to do the above (except the last), but delayed expansion is the easiest, most efficient (fastest to execute), and most reliable option.

Major Disadvantage

  • Any FOR variable that contains ! in its value will be corrupted when it is expanded if delayed expansion is enabled. I frequently toggle delayed expansion on and off within a FOR loop to get around the problem.
  • It is not good for executing a "macro" (executing code contained within a variable value) because many important phases of command parsing take place prior to the delayed expansion. So many batch features are unavailable to "macros" that are executed via delayed expansion.
like image 85
dbenham Avatar answered Nov 14 '22 17:11

dbenham