在Windows批处理文件中编写脚本时,有时正确执行脚本需要使用setlocal
命令。我关于使用setlocal
的主要抱怨是,我经常表现出复杂的& if语句,我在该段代码中设置变量值。发出命令endlocal
时,这些设置会丢失。
到目前为止,我通过将变量值回显到setlocal
段中的暂存文件中然后将值读回endlocal
之后的变量来解决此问题。但是,似乎应该有一个更优雅的解决方案。
如果仅使用一个或多个set
语句,建议的答案提供了一种绕过问题的便捷方法。但是,当setlocal
到位以允许for
循环在执行时正确扩展变量名而不是解析时,链接的答案不提供解决方案。在我的情况下,我还有if
语句逻辑树来进一步检查该信息到set
许多不同的可能变量值。链接的解决方案无法解决这种情况。
此代码应检查安装包的版本号。它是从另一个需要版本号才能正常运行的脚本调用的。我们知道包是使用[应用程序] [版本号] .msi的形式命名的。 [版本号]可以是以下任何一种:
指定目录中可能存在多个安装包,因此查看所有安装包并在目录中选择最高版本非常重要。
我继承并扩展了代码以正确处理10& 10.1版本。如果没有setlocal有更好的方法来做到这一点(例如,我已经考虑过重写以使用案例陈述),我很乐意看到更好的解决方案。
但是,我仍然有兴趣学习如何将变量传递出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
)?
答案 0 :(得分:3)
要保留setlocal / endlocal范围内的变量,存在不同的解决方案。
这取决于您应该使用哪种情况。
只使用简单内容的括号块之外的,但可以产生特殊字符的问题,例如!^"
。
setlocal
set localVar=something simple
...
(
endlocal
set "out=%localVar%"
)
set out
也可以在块中使用并且可以处理大多数字符,但可能会因!^
和换行/回车而失败
if 1==1 (
setlocal EnableDelayedExpansion
set "localVar=something medium nasty & "^&"
for /F "delims=" %%V in ("!localVar!") DO (
endlocal
set "out=%%V"
)
)
set out
适用于任何情况下的所有内容
SO: preserving exclamation marks in variable between setlocals batch