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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7883169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:51:50  来源:igfitidea点击:

How to escape variables with parentheses inside if-clause in a batch file?

windowscommand-linebatch-fileescaping

提问by Piotr Dobrogost

Running this batch file

运行这个批处理文件

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

gives inside was unexpected at this time.error.

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

How to escape avariable to avoid this error?

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

回答by jeb

You can use two different ways

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

Use the extended syntax of setwith quotes set "var=content"will set var with content, content is quoted so special characters aren't problematic and it uses the content till the last quote (without the quote itself)

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

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

Use delayed expansion (like the answer of shf301) but also transfer the value to the main scope.

使用延迟扩展(如 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"
    )
)

In this case the extended set-syntax is not necessary, I used it only to avoid hidden spaces at the line end.

在这种情况下,扩展 set-syntax 不是必需的,我使用它只是为了避免行尾的隐藏空间。

EDIT:Can I combine this with setlocal EnableDelayedExpansion and using ! instead of % to lazy evaluate variable's value? When I tried I got )! was unexpected at this time.

编辑:我可以将它与 setlocal EnableDelayedExpansion 结合使用吗?而不是 % 来懒惰评估变量的值?当我尝试时,我得到了)!没想到此时。

You can, but it's contra productive, as

你可以,但它的生产力适得其反,因为

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

Then your path contains carets in front of the )like C:\programs (x86^)

那么你的路径包含脱字在前面)C:\programs (x86^)

To understand how expansion works you can read SO:How does the Windows Command Interpreter (CMD.EXE) parse scripts?

要了解扩展的工作原理,您可以阅读SO:Windows 命令解释器 (CMD.EXE) 如何解析脚本?

EDIT2: More problems with the path (containing quotes)
According to this questionthere can occour another problem with parenthesis when the path contains quotes.

EDIT2: More questions with the path (包含引号)
根据这个问题,当路径包含引号时,括号可能会出现另一个问题。

Sample
path="C:\Program Files (x86)";C:\Program Files (x86)\Skype

样本
path="C:\Program Files (x86)";C:\Program Files (x86)\Skype

This is allowed, even it's not necessary to use quotes here, but this destroys the extended SETsyntax, as now set "newPath=%path%"expands to

这是允许的,即使在这里没有必要使用引号,但这会破坏扩展SET语法,现在set "newPath=%path%"扩展为

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

Now at least one parenthesis is not inside quotes and is able to break a command block.

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

But you can simply remove all quotes from the path variable, as said, quotes aren't necessary here.

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

set "newPath=%path:"=%"

回答by Patrick Seymour

The )in %a%is the problem here. You can just do some substitution to escape the ).

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

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

回答by shf301

Using delayed expansion will fix that:

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

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

Without delayed expansion the if block (from the ifto the ending ), %a% is replaced first and then the block is parsed and run. With delayed expansion !a! isn't expanded after the block parsed. So the parsing logic won't see the ) in aand won't cause it issues.

没有延迟扩展 if 块(从 theif到结尾),首先替换 %a% 然后块被解析并运行。延迟扩展!a!在块解析后不会扩展。所以解析逻辑不会看到 )a并且不会导致它的问题。

回答by Hand-E-Food

Brackets and variables are always a pain to mix. Use a subroutine instead.

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

@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

I set the variable twice, once using Setfor the current shell session, and one using SetXto set it system-wide for future shell sessions. Remove either if they're unneeded.

我设置了两次变量,一次使用Set用于当前的 shell 会话,另一次使用SetX在系统范围内设置它以供将来的 shell 会话使用。如果不需要,请将其删除。