【问题标题】:How to escape variables with parentheses inside if-clause in a batch file?如何在批处理文件的 if 子句中使用括号转义变量?
【发布时间】:2011-10-19 18:57:01
【问题描述】:

运行这个批处理文件

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

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

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

【问题讨论】:

    标签: windows command-line batch-file escaping


    【解决方案1】:

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

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

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

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

    @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"
        )
    )
    

    在这种情况下,扩展集合语法不是必需的,我使用它只是为了避免行尾的隐藏空格。

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

    你可以,但它是相反的,因为

    @echo off
    Setlocal EnableDelayedExpansion
    set a=some value with (parentheses) inside
    if 1 == 1 (
        set PATH=!a:^)=^^^)!
        set path
    )
    

    那么你的路径在) 前面包含插入符号,例如 C:\programs (x86^)

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

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

    示例
    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"
    

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

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

    set "newPath=%path:"=%"
    

    【讨论】:

    • set "var=content" - 谁能猜到? :)
    • 在这种情况下扩展的集合语法是不必要的你能解释一下吗?
    • 我更喜欢它,因为它避免了行尾隐藏空格的问题
    • 我在问为什么没有必要不是你使用它的原因:)
    • 顺便说一句,我可以联系你吗?
    【解决方案2】:

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

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

    【讨论】:

    • 我可以将它与setlocal EnableDelayedExpansion 结合使用并使用! 而不是% 来懒惰地评估变量的值吗?当我尝试时,我得到了)! was unexpected at this time. 错误。
    • 你可以组合它,但这不是必需的,因为延迟扩展对任何特殊字符都是安全的,)
    • 我会使用延迟扩展或我的方法,而不是两者。只是一个意见。
    【解决方案3】:

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

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

    没有延迟扩展 if 块(从 if 到结尾 ),首先替换 %a% 然后解析并运行该块。延迟扩展 !a! 在块之后不扩展已解析。因此解析逻辑不会在 a 中看到 ) 并且不会导致它出现问题。

    【讨论】:

    • 好吧,你修改了 local PATH 变量。你打算如何转移这个值到全局范围?
    • 在我的回答中是将变量转移到全局范围的示例
    【解决方案4】:

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

    @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 会话。如果不需要,请删除它们。

    【讨论】:

      猜你喜欢
      • 2012-10-10
      • 2010-12-30
      • 1970-01-01
      • 2022-01-07
      • 2017-04-21
      • 2010-11-22
      • 2019-06-20
      • 1970-01-01
      相关资源
      最近更新 更多