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
How to escape variables with parentheses inside if-clause in a batch file?
提问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 a
variable to avoid this error?
如何转义a
变量以避免此错误?
回答by jeb
You can use two different ways
您可以使用两种不同的方式
Use the extended syntax of set
with 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)
使用set
with 引号的扩展语法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 (包含引号)
根据这个问题,当路径包含引号时,括号可能会出现另一个问题。
Samplepath="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 SET
syntax, 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 if
to 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 a
and 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 会话使用。如果不需要,请将其删除。