如何解决是EnableDelayedExpansion还是呼叫集?
set /p "PROGNAME=enter the name of the prog: "
set /p "VERSION=enter the version of the prog: "
setlocal enabledelayedexpansion
if "%PROGNAME%"=="foo" (
set "OPTIONS=(someParams)"
set "PROGPATH=C:\MyPath\%PROGNAME%%OPTIONS%_%VERSION%.exe"
) else if "%PROGNAME%"=="bar" (
set "OPTIONS=(otherParams)"
set "PROGPATH=C:\MyPath\%PROGNAME%%OPTIONS%_%VERSION%.exe"
)
set "PROGDLL=!PROGPATH:%PROGNAME%=%PROGNAME%dll!"
endlocal
我了解到enabledelayedexpansion
变量都需要PROGPATH
,因为它与变量OPTIONS
和PROGDLL
处于同一循环中变量,因为替换。
但是,在这种特殊情况下,我不希望变量是局部的。就像,一点也不;即使在脚本结束后,我也想访问它们。因此无法使用enabledelayedexpansion
。
然后我做了这样的事情:
set /p "PROGNAME=enter the name of the prog: "
set /p "VERSION=enter the version of the prog: "
if "%PROGNAME%"=="foo" (
set "OPTIONS=(someParams)"
call set "PROGPATH=C:\MyPath\%PROGNAME%%OPTIONS%_%VERSION%.exe"
call set "PROGDLL=%%PROGPATH:foo=foodll%%"
) else if "%PROGNAME%"=="bar" (
set "OPTIONS=(otherParams)"
call set "PROGPATH=C:\MyPath\%PROGNAME%%%OPTIONS%%_%VERSION%.exe"
call set "PROGDLL=%%PROGPATH:bar=bardll%%"
)
尽管这很好用,但我现在很迷失:如果只需要一个call set
,enabledelayedexpansion
的意义是什么?我的意思是,每次需要在循环中设置一些因变量时,我都会在脚本中使用enabledelayedexpansion
,是否应该将所有变量替换为call set
并删除enabledelayedexpansion
?
一般来说,我想了解何时应该使用enabledelayedexpansion
和何时应该使用call set
。
(还有为什么将%%
与call set
一起使用?)
解决方法
好吧,您的代码实际上应该像这样:
rem // At this point,the default state should apply,hence no delayed expansion:
set /P "PROGNAME=enter the name of the prog: "
set /P "VERSION=enter the version of the prog: "
setlocal EnableDelayedExpansion
rem /* At this point,delayed expansion should be applied for all possible variables,rem because otherwise,you may run into problems with exclamation marks: */
if "!PROGNAME!"=="foo" (
set "OPTIONS=(someParams)"
rem /* You need `!OPTIONS!` here,of course,since it is set in the same block;
rem but you should also use `!PROGNAME!` and `!VERSION!` herein: */
set "PROGPATH=C:\MyPath\!PROGNAME!!OPTIONS!_!VERSION!.exe"
) else if "!PROGNAME!"=="bar" (
set "OPTIONS=(otherParams)"
set "PROGPATH=C:\MyPath\!PROGNAME!!OPTIONS!_!VERSION!.exe"
)
rem /* For the sub-string substitution,you should avoid immediate expansion,rem because you may get in trouble with unbalanced quotes,if applicable;
rem you could use a `for /F` loop to delay expansion of search/replace strings;
rem as you can see,delayed expansion is used as much as possible,and
rem the whole replacement expression is transferred to the `for` meta-variable: */
for /F "delims=" %%S in ("!PROGNAME!=!PROGNAME!dll") do set "PROGDLL=!PROGPATH:%%I!"
rem /* To avoid loss of set variables due to end of the environment localisation,rem use another `for /F` loop; delayed expansion is used as much as possible,and
rem the whole assignment expression is transferred to the `for` meta-variable: */
for /F "delims=" %%E in ("PROGPATH=!PROGPATH!") do endlocal & set "%%E"
请注意,设置的变量仅在运行批处理脚本的同一cmd.exe
实例中可用。
如果您要使用call
而不是延迟扩展,则代码应为:
rem // At this point,hence no delayed expansion:
set /P "PROGNAME=enter the name of the prog: "
set /P "VERSION=enter the version of the prog: "
setlocal EnableDelayedExpansion
if "%PROGNAME%"=="foo" (
set "OPTIONS=(someParams)"
rem // You need `call` here,since `OPTIONS` is set in the same block:
call set "PROGPATH=C:\MyPath\%PROGNAME%%%OPTIONS%%_%VERSION%.exe"
rem /* Here is an alternative way using `%%` for all variables,which may avoid
rem problems with unbalanced quotes,but you may get unwanted `^`-doubling: */
rem call set "PROGPATH=C:\MyPath\%%PROGNAME%%%%OPTIONS%%_%%VERSION%%.exe"
) else if "!PROGNAME!"=="bar" (
set "OPTIONS=(otherParams)"
call set "PROGPATH=C:\MyPath\%PROGNAME%%%OPTIONS%%_%VERSION%.exe"
rem call set "PROGPATH=C:\MyPath\%%PROGNAME%%%%OPTIONS%%_%%VERSION%%.exe"
)
rem // Of course you will need `call` for the sub-string substitution:
call set "PROGDLL=%%PROGPATH:%PROGNAME%=%PROGNAME%dll%%"
但是请注意,这种方法比较慢,并且插入符号^
可能会不必要地加倍,您可能会遇到麻烦。此外,%%
可能会引起for
元变量的意外扩展,例如,当代码放置在%%P
适用的部分内时,call set "PROGDLL=%%PROGPATH:…%%"
将导致因为%%P
部分已扩展。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。