Batch file IF块内变量中的括号

Batch file IF块内变量中的括号,batch-file,parentheses,Batch File,Parentheses,在我的一个脚本中,我需要在IF语句中使用包含括号的变量,但字符串缺少一个右括号,或者脚本过早退出,此时*出乎意料(实际上不是星号),具体取决于场景 示例 @echo off SET path=%programFiles(x86)% echo Perfect output: %path% IF NOT "%path%" == "" ( REM Variable is defined echo Broken output: %path% ) pause >nul 输

在我的一个脚本中,我需要在
IF
语句中使用包含括号的变量,但字符串缺少一个右括号,或者脚本过早退出,此时
*出乎意料(实际上不是星号),具体取决于场景

示例

@echo off

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

pause >nul
输出

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

我认为/知道这是因为它认为
C:\ProgramFiles(x86)
中的右括号是
IF
语句的结尾,它在
echo
完成之前退出

有没有简单的方法来解决这个问题?最好不要诉诸法律

  • 单行
    IF
    语句,因为我需要在其中运行多行代码
  • 大量的
    GOTO
    s,因为它不实用
  • setlocalenabledelayedexpansion
    并使用
    !路径
    而不是
    %path%
    ,因为我记得在某个地方读到,该方法在OSs中并不一致
  • 如果没有,我会乐意接受最可靠的解决方案,不管它是什么


    (这个场景不值得讨论。这只是一个精致、集中的问题示例。结构应该是这样的,就像我的实际脚本中一样,因为我不想讨论的原因。这不符合重点,只会混淆事情,分散对实际问题的注意力。)

    如果我读错了,请原谅,但“不是”这个词不是吗导致控件进入括号中的if并运行中断的输出

    那么:

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

    echo
    语句中解析变量的
    过早关闭
    IF

    通常,您可以通过使用
    ^)
    转义
    来解决这个问题,但不能修改环境变量以解析为
    C:\Program Files(x86^)

    可以通过在变量周围加引号来防止此问题

    作为一个简单的例子:

    > SET bad=a)b
    > IF 1 == 1 ( ECHO %bad% )
    b was unexpected at this time.
    > IF 1 == 1 ( ECHO "%bad%" )
    "a)b"
    

    首先-您不应该将PATH变量用于自己的用途。它是一个保留的环境变量。将其用于您自己的目的可能会破坏您的脚本

    最简单的解决方案实际上是使用延迟扩展。只要您的平台使用CMD.EXE,您就可以访问延迟扩展

    但有一种相对简单的方法可以让它在不延迟扩张的情况下运行。你可以用引号。在解析命令时,引号作为FOR变量的名称在解析时存在。它在执行时间之前扩展为零

    @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
    
    编辑-何时使用延迟扩展:回复评论

    Perfect output: C:\Program Files (x86)
    Broken output:  C:\Program Files (x86
    
    我通常只在需要的时候(或者更准确地说,在有利的时候)使用延迟扩展。也就是说,我通常发现它在批处理代码的某些部分是有利的

    主要优势

    • 在代码块内查看对块内变量的更改
    • 取消引用变量名称时。如果变量名作为参数传入,则可以通过延迟扩展获取变量值:
      echo!%1!
    • 当使用变量作为参数来搜索和替换或子字符串操作时:
      echo!变量:%search%=%replace%
      回声!变量:%start%,%len%
    • 每当我需要扩展值时,不必担心其中的特殊字符需要转义或引用:
      set“var=A&B”&echo!瓦尔
    有其他方法可以实现上述功能(除了最后一种),但延迟扩展是最简单、最有效(执行速度最快)和最可靠的选择

    主要缺点

    • 包含
      的变量的任意值将被损坏。我经常在FOR循环中打开和关闭延迟扩展,以解决问题
    • 它不适合执行“宏”(执行包含在变量值中的代码),因为命令解析的许多重要阶段都发生在延迟扩展之前。通过延迟扩展执行的“宏”无法使用许多批处理功能
      • 我的建议是:

        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
        

        正如其他人已经指出的,未转义和未加引号的右括号
        无意中结束了带括号的
        if

        除了转义、引号和“消失引号”之外,还有以下其他选项:

      • 对引用的值使用元变量,并通过以下方式删除引用:

        @echo关闭
        设置“路径=%ProgramFiles(x86)%”
        回声完美输出:%PATH%
        如果不是“%PATH%”,则为(
        定义了rem变量
        对于(“%PATH%”)中的%%P,是否回显未中断的输出:%%~P
        )
        暂停>nul
        
      • 使用启动另一个变量扩展阶段,以及加倍(转义)
        %
        -符号:

        @echo关闭
        设置“路径=%ProgramFiles(x86)%”
        回声完美输出:%PATH%
        如果不是“%PATH%”,则为(
        定义了rem变量
        调用回显未中断输出:%%PATH%%
        )
        暂停>nul
        
      • 在检测到之前进行转义:

        @echo关闭
        设置“路径=%ProgramFiles(x86)%”
        回声完美输出:%PATH%
        如果不是“%PATH%”,则为(
        定义了rem变量
        回显未中断的输出:%PATH:)=^)%
        )
        暂停>nul
        

      • NOT
        用于确保变量在输出所述值之前有一个值(在本例中,它有)。
        NOT
        是不相关的,它发生在任何使用括号的代码块中。你误解了这个问题。你会这么想的,不是吗?我才意识到它可能会被误解,所以我把它改回原来的样子。@BenHooper:仔细阅读。问题来自已解决的变量
        cmd
        将其转换为
        C:\P