如何在批处理文件中使用if子句中的括号转义变量?

时间:2011-10-19 18:57:02

标签: windows command-line batch-file escaping

运行此批处理文件

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=%a%
)

给出inside was unexpected at this time.错误。

如何转义a变量以避免此错误?

4 个答案:

答案 0 :(得分:27)

您可以使用两种不同的方式

使用带引号set的{​​{1}}扩展语法将var设置为内容, 内容被引用,所以特殊字符没有问题,它使用内容,直到最后一个引用(没有引号本身)

set "var=content"

使用延迟扩展(如shf301的答案),但也将值传输到主范围。

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set "PATH=%a%"
)

在这种情况下,扩展的set-syntax不是必需的,我只用它来避免行末端的隐藏空格。

修改 我可以将它与setlocal EnableDelayedExpansion结合使用!而不是%到懒惰评估变量的值?当我尝试时,我得到了)!这时出人意料。

你可以,但它的效率很高,因为

@echo off
setlocal enabledelayedexpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set "localScope_PATH=!a!"
    rem now transfer it to the global scope
    FOR /F "delims=" %%A in ("!localScope_PATH!") DO (
       endlocal
       set "path=%%A"
    )
)

然后你的路径包含@echo off Setlocal EnableDelayedExpansion set a=some value with (parentheses) inside if 1 == 1 ( set PATH=!a:^)=^^^)! set path ) 之前的插入符号 )

要了解扩展的工作原理,您可以阅读SO:How does the Windows Command Interpreter (CMD.EXE) parse scripts?

EDIT2:路径更多问题(包含引号)
根据这个question,当路径包含引号时,可能会出现括号的另一个问题。

样品
C:\programs (x86^)

这是允许的,即使没有必要在这里使用引号,但这会破坏扩展的path="C:\Program Files (x86)";C:\Program Files (x86)\Skype语法,因为现在SET扩展为

set "newPath=%path%"

现在至少有一个括号不在引号内,并且能够破坏命令块。

但你可以简单地从路径变量中删除所有引号,如上所述,这里不需要引号。

set "newPath="C:\Program Files (x86)";C:\Program Files (x86)\Skype"

答案 1 :(得分:4)

)中的%a%是问题所在。你可以做一些替换来逃避)

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=%a:)=^)%
)

答案 2 :(得分:2)

使用延迟扩展将解决这个问题:

@echo off
setlocal enabledelayedexpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=!a!
)

如果没有延迟扩展if块(从if到结束),首先替换%a%,然后解析并运行块。延迟扩展!a!不是在块解析后展开。因此解析逻辑将不会在a中看到并且不会导致问题。

答案 3 :(得分:2)

括号和变量总是很难混合。改为使用子程序。

@Echo Off
Set a=some value with (parentheses) inside
If 1 == 1 Call :SetPath
Echo %Path%
Exit /B

:SetPath
Set "Path=%a%"
SetX "Path" "%a%"
Exit /B

我将变量设置两次,一次使用Set进行当前shell会话,另一次使用SetX将系统设置为未来的shell会话。如果不需要,请删除。