在Windows批处理文件中编写脚本时,有时脚本的正确执行需要使用setlocal
命令。我对使用setlocal
的主要提示是,我经常为&if语句执行复杂的操作,其中我在代码的该部分中设置了变量值。当我发出命令endlocal
时,这些设置会丢失。
到目前为止,我已经通过将变量值回显到setlocal
段内的暂存文件中,然后在endlocal
之后将值读回到变量中来解决此问题。但是,似乎应该有一个更优雅的解决方案。
如果仅使用一个或多个set
语句,建议的答案将提供一种解决问题的简便方法。但是,当放置了setlocal
时,链接的答案未提供解决方案,以允许for
循环在执行时(而不是进行分析时)正确扩展变量名。在我的情况下,我还有if
语句逻辑树,可以对该信息执行进一步的检查,以便set
许多不同的可能变量值。链接的解决方案不提供这种情况的解决方案。
该代码应该检查安装软件包的版本号。它是从另一个需要该版本号才能正常运行的脚本中调用的。我们知道该软件包是使用[application] [version number] .msi形式命名的。 [版本号]可以是以下任意一个:
指定目录中可能存在多个安装包,因此仔细检查所有安装包并选择目录中的最高版本很重要。
我继承并扩展了代码以正确处理10和10.1版本。如果没有setlocal的话还有更好的方法(例如,我考虑过重写以使用case语句),我很乐意看到更好的解决方案。
但是,我仍然对学习如何将变量传递到
setlocal
/endlocal
段中感兴趣。setlocal enabledelayedexpansion
for /f %%a in ('dir /b program*.MSI') do (
set FileName=%%a
set tst1=!FileName:~4,3!
if "!tst1!" == "msi" (
rem Only true if it has a 1 digit number (e.g. "9")
set MAIN_VERSION=!FileName:~2,1!
) else (
set tst2=!FileName:~5,3!
if "!tst2!" == "msi" (
rem Only true if it has a 2 digit version number (e.g. "10")
set MAIN_VERSION=!FileName:~2,2!
) else (
... lots more code ...
)
)
)
rem Write results out to a file for temporary storage. This particular
rem form of echo is required to ensure there are no trailing spaces, CR,
rem or LF
echo|set /P ="!MAIN_VERSION!" > %USERPROFILE%\UGV.txt
rem End local variables
endlocal
rem Read the correct version out of our temporary storage file
set /p MAIN_VERSION=<%USERPROFILE%\UGV.txt
如何在不使用暂存文件的情况下从Windows批处理脚本
MAIN_VERSION
/setlocal
代码段中传递变量(例如上面的endlocal
)? 最佳答案
为了在setlocal/endlocal范围内保留变量,存在不同的解决方案。
这取决于您应该使用哪种情况。
1)简单
只能在带简单内容的括号块之外使用,但是可以使用特殊字符像!^"
产生问题。setlocal
set localVar=something simple
...
(
endlocal
set "out=%localVar%"
)
set out
2)中
也可以在块中工作,并且可以处理最多的字符,但是由于!^
和换行符/回车符而失败if 1==1 (
setlocal EnableDelayedExpansion
set "localVar=something medium nasty & "^&"
for /F "delims=" %%V in ("!localVar!") DO (
endlocal
set "out=%%V"
)
)
set out
3)高级
在任何情况下都适用于所有内容
SO: preserving exclamation marks in variable between setlocals batch