微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是EnableDelayedExpansion还是呼叫集?

如何解决是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,因为它与变量OPTIONSPROGDLL处于同一循环中变量,因为替换。

但是,在这种特殊情况下,我不希望变量是局部的。就像,一点也不;即使在脚本结束后,我也想访问它们。因此无法使用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 setenabledelayedexpansion的意义是什么?我的意思是,每次需要在循环中设置一些因变量时,我都会在脚本中使用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 举报,一经查实,本站将立刻删除。