在复合 IF 语句中使用带括号的环境变量,如 %ProgramFiles(x86)% 会引发意外错误
Using environment variable with parens, like %ProgramFiles(x86)% in a compound IF-statement raises unexpected errors
我尝试了以下场景 with/without delayedExpansion
(编辑:Squashman 在评论中解释说不需要延迟扩展)
当我尝试设置使用 !ProgramFiles(x86)!
或 %ProgramFiles(x86)%
的环境变量时收到不可预知的错误
示例:
@echo off
rem With or without this, with/without "!" or "%", fails on "SET"
setlocal EnableDelayedExpansion
if exist "!ProgramFiles(x86)!\Microsoft Visual Studio\Installer" (
set INSTALLVS=!ProgramFiles(x86)!\Microsoft Visual Studio\Installer
)
echo !INSTALLVS!
结果:
d:\test>runbatch.cmd
!\Microsoft was unexpected at this time.
添加引号有效(如 SET="%ProgramFile..."
,但后来我 运行 遇到了麻烦,在组合路径时不得不删除引号),或者临时变量有效:
@echo off
rem Works correctly
setlocal EnableDelayedExpansion
set INSTALLTMP=!ProgramFiles(x86)!\Microsoft Visual Studio\Installer
if exist "!INSTALLTMP!" (
set INSTALLVS=!INSTALLTMP!
set INSTALLTMP=
)
echo !INSTALLVS!
发生这种情况:
- 当
delayedExpansion
开启或关闭时
- 无论哪种情况我都使用
%
或 !
不会发生在什么时候:
- 在
IF
声明之外
SET
参数被引用:SET foo="%ProgramFiles(x86)%"
,但这会将引号添加到该参数的值
我在这里做错了什么/误解了什么?
问题出在关闭 IF
块的右括号。有没有延期扩张都没有关系。
- 某些语句,如
echo
、rem
、::
在包含右括号时可以正常工作。
- 大多数其他语句,如
set
、copy
、goto
、md
等都不起作用,没有引号的右括号将关闭IF 块。
- 出于同样的原因,复合语句(如
echo hello > foo(32).txt
)不起作用。
- 如果右括号是您使用的环境变量名称的一部分,它也可能会使 IF 块短路
- 作为嵌套 IF 或 DO 块一部分的右括号是安全的,允许嵌套
解决方案是在命令允许的情况下将右括号放在引号中,或者将其转义,即:!ProgramFiles^(x86^)!
(仅适用于 enableDelayedExpansion
)。
例如:
@echo off
setlocal enabledelayedexpansion
if exist "!ProgramFiles(x86)!\Microsoft Visual Studio\Installer" (
set "INSTALLVS=!ProgramFiles(x86)!\Microsoft Visual Studio\Installer"
)
echo !INSTALLVS!
if exist "!ProgramFiles(x86)!\Microsoft Visual Studio\Installer" (
set INSTALLVS=!ProgramFiles^(x86^)!\Microsoft Visual Studio\Installer
)
echo %INSTALLVS%
setlocal disabledelayedexpansion
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer" (
set "INSTALLVS=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"
)
echo %INSTALLVS%
pause
输出
C:\Program Files (x86)\Microsoft Visual Studio\Installer
C:\Program Files (x86)\Microsoft Visual Studio\Installer
C:\Program Files (x86)\Microsoft Visual Studio\Installer
Press any key to continue . . .
我尝试了以下场景 with/without delayedExpansion
(编辑:Squashman 在评论中解释说不需要延迟扩展)
当我尝试设置使用 !ProgramFiles(x86)!
或 %ProgramFiles(x86)%
示例:
@echo off
rem With or without this, with/without "!" or "%", fails on "SET"
setlocal EnableDelayedExpansion
if exist "!ProgramFiles(x86)!\Microsoft Visual Studio\Installer" (
set INSTALLVS=!ProgramFiles(x86)!\Microsoft Visual Studio\Installer
)
echo !INSTALLVS!
结果:
d:\test>runbatch.cmd
!\Microsoft was unexpected at this time.
添加引号有效(如 SET="%ProgramFile..."
,但后来我 运行 遇到了麻烦,在组合路径时不得不删除引号),或者临时变量有效:
@echo off
rem Works correctly
setlocal EnableDelayedExpansion
set INSTALLTMP=!ProgramFiles(x86)!\Microsoft Visual Studio\Installer
if exist "!INSTALLTMP!" (
set INSTALLVS=!INSTALLTMP!
set INSTALLTMP=
)
echo !INSTALLVS!
发生这种情况:
- 当
delayedExpansion
开启或关闭时 - 无论哪种情况我都使用
%
或!
不会发生在什么时候:
- 在
IF
声明之外 SET
参数被引用:SET foo="%ProgramFiles(x86)%"
,但这会将引号添加到该参数的值
我在这里做错了什么/误解了什么?
问题出在关闭 IF
块的右括号。有没有延期扩张都没有关系。
- 某些语句,如
echo
、rem
、::
在包含右括号时可以正常工作。 - 大多数其他语句,如
set
、copy
、goto
、md
等都不起作用,没有引号的右括号将关闭IF 块。 - 出于同样的原因,复合语句(如
echo hello > foo(32).txt
)不起作用。 - 如果右括号是您使用的环境变量名称的一部分,它也可能会使 IF 块短路
- 作为嵌套 IF 或 DO 块一部分的右括号是安全的,允许嵌套
解决方案是在命令允许的情况下将右括号放在引号中,或者将其转义,即:!ProgramFiles^(x86^)!
(仅适用于 enableDelayedExpansion
)。
例如:
@echo off
setlocal enabledelayedexpansion
if exist "!ProgramFiles(x86)!\Microsoft Visual Studio\Installer" (
set "INSTALLVS=!ProgramFiles(x86)!\Microsoft Visual Studio\Installer"
)
echo !INSTALLVS!
if exist "!ProgramFiles(x86)!\Microsoft Visual Studio\Installer" (
set INSTALLVS=!ProgramFiles^(x86^)!\Microsoft Visual Studio\Installer
)
echo %INSTALLVS%
setlocal disabledelayedexpansion
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer" (
set "INSTALLVS=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"
)
echo %INSTALLVS%
pause
输出
C:\Program Files (x86)\Microsoft Visual Studio\Installer
C:\Program Files (x86)\Microsoft Visual Studio\Installer
C:\Program Files (x86)\Microsoft Visual Studio\Installer
Press any key to continue . . .