IF块内变量的括号

时间:2012-08-14 00:19:01

标签: batch-file parentheses

在我的一个脚本中,我需要在IF语句中使用包含括号的变量,但是字符串缺少右括号或脚本过早地以* was unexpected at this time退出(实际上不是星号) ),取决于场景。

示例

@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:\Program Files (x86)中的右括号是IF语句的结尾,它会在echo完成之前退出。

有没有简单的方法来解决这个问题?最好不要求助于

  1. 单行IF语句,因为我需要在其中运行多行代码,
  2. 大量GOTO s,因为它不实用,
  3. SETLOCAL EnableDelayedExpansion并使用!path!代替%path%,因为我记得曾在某处读过该方法在操作系统中无法一致地工作。
  4. 如果没有,我很乐意接受所提供的最可靠的解决方案,无论它是什么。

    (这个场景不值得讨论。这只是问题的一个精炼,集中的例子。结构需要像这样,因为它在我的实际脚本中,原因我不会进入。除了这一点之外,它只会混淆事物并分散实际问题。)

5 个答案:

答案 0 :(得分:7)

首先 - 你永远不应该使用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

编辑 - 何时使用延迟展开:对评论的回复

我通常只在需要时使用延迟扩展(或者更确切地说,当它有利时)。话虽这么说,我通常发现它在我的批处理代码的某些部分是有利的。

主要优势

  • 在代码块内部,以便查看块内变量的更改
  • 取消引用变量名称时。如果变量名称作为参数传入,则可以通过延迟扩展获取变量的值:echo !%1!
  • 使用变量作为搜索和替换或子字符串操作的参数时:echo !var:%search%=%replace%!echo !var:%start%,%len%!
  • 每当我需要扩展价值而不担心其中需要转义或引用的特殊字符时,set "var=A&B" & echo !var!

还有其他方法可以执行上述操作(除了最后一个),但延迟扩展是最简单,最有效(最快的执行)和最可靠的选项。

主要缺点

  • 如果启用了延迟扩展,则展开其值时包含!的任何FOR变量都将被破坏。我经常在FOR循环中打开和关闭延迟扩展以解决问题。
  • 执行“宏”(执行变量值中包含的代码)并不好,因为命令解析的许多重要阶段都发生在延迟扩展之前。如此多的批处理功能对于通过延迟扩展执行的“宏”是不可用的。

答案 1 :(得分:1)

)语句中已解析变量的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"

答案 2 :(得分:1)

我的建议是:

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

答案 3 :(得分:0)

原谅我,如果我读错了,但是不是“NOT”导致控制进入括号中并输出破损的输出?

怎么样:

@echo off

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

pause >nul

答案 4 :(得分:0)

正如其他人已经指出的那样,未转义且未加引号的右括号)会无意地结束带括号的if块。

除了转义,引号,delayed expansion和“消失的引号”外,还有以下其他选择:

  1. 对引号使用for元变量,并用~-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. 使用call command来启动另一个变量扩展阶段,并将%符号加倍(转义):

     @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. 通过sub-string substitution进行转义,这是在检测到^-escaping之前发生的:

     @echo off
    
     set "PATH=%ProgramFiles(x86)%"
     echo Perfect output:  %PATH%
     if not "%PATH%" == "" (
         rem Variable is defined
         echo Unbroken output: %PATH:)=^)%
     )
    
     pause > nul