Parenthesis in variables inside IF blocks

后端 未结 5 1022
天命终不由人
天命终不由人 2021-02-07 12:12

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 ex

相关标签:
5条回答
  • 2021-02-07 12:45

    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.
    0 讨论(0)
  • 2021-02-07 12:48

    As others already pointed out, the unescaped and unquoted closing parenthesis ) unintentionally ends the parenthesised if block.

    Besides escaping, quotation, delayed expansion and "disappearing quotes", there are the following further options:

    1. Use a for meta-variable on the quoted value and remove the quotes by the ~-modifier:

       @echo off
      
       set "PATH=%ProgramFiles(x86)%"
       echo Perfect output:  %PATH%
       if not "%PATH%" == "" (
           rem Variable is defined
           for %%P in ("%PATH%") do echo Unbroken output: %%~P
       )
      
       pause > nul
      
    2. Use the call command to initiate another variable expansion phase, together with doubled (escaped) %-symbols:

       @echo off
      
       set "PATH=%ProgramFiles(x86)%"
       echo Perfect output:  %PATH%
       if not "%PATH%" == "" (
           rem Variable is defined
           call echo Unbroken output: %%PATH%%
       )
      
       pause > nul
      
    3. Do escaping by sub-string substitution, which happens before ^-escaping is detected:

       @echo off
      
       set "PATH=%ProgramFiles(x86)%"
       echo Perfect output:  %PATH%
       if not "%PATH%" == "" (
           rem Variable is defined
           echo Unbroken output: %PATH:)=^)%
       )
      
       pause > nul
      
    0 讨论(0)
  • 2021-02-07 12:58

    my suggestion is :

    if (condition_TRUE) goto goodbye_parenthesis_BEGIN
    
    goto goodbye_parenthesis_END  ----- line when previous condition is FALSE ----
    :goodbye_parenthesis_BEGIN ----- line when previous condition is TRUE ----
    
    ...
    variable treatment
    ...
    
    :goodbye_parenthesis_END
    
    0 讨论(0)
  • 2021-02-07 13:00

    The ) from the resolved variable in your echo statement is prematurely closing the IF block.

    Ordinarily, you could fix that by escaping the ) with ^), but you can't modify the environment variable to resolve to C:\Program Files (x86^).

    You can prevent this issue by surrounding the variable with quotes.

    As a simpler example:

    > SET bad=a)b
    > IF 1 == 1 ( ECHO %bad% )
    b was unexpected at this time.
    > IF 1 == 1 ( ECHO "%bad%" )
    "a)b"
    
    0 讨论(0)
  • 2021-02-07 13:06

    Forgive me if I'm reading this wrong, but isn't the "NOT" causing control to enter the bracketed if and run the broken output?

    what about:

    @echo off
    
    echo Perfect output: %programFiles(x86)%
    IF NOT "%programFiles(x86^)%" ==  "" (
        REM Variable is defined
        echo Broken output:  %programFiles(x86)%
    ) 
    
    pause >nul
    

    ?

    0 讨论(0)
提交回复
热议问题