批处理文件不保留变量

时间:2016-09-21 21:21:15

标签: variables batch-file cmd

为什么以下批处理文件在CMD.exe终止时保留变量

@echo off
cmd /c "set var=hi"
if defined var (echo var is defined ("var=%var%")) else (echo var isn't defined)
pause
exit

有没有办法使用CMD / c,同时保留变量?为什么CMD / c不保留变量?

1 个答案:

答案 0 :(得分:3)

CMD / C启动一个新的子进程,该进程有自己的环境空间,其中变量存储在内存中。当该进程终止时,相关的环境空间将丢失,因此您当然会丢失在那里定义的任何变量的定义。

子流程不可能直接访问或操纵父流程的变量。

如果您正在执行一个简单的命令并控制任何输出,那么您可以将定义写入stdout并让FOR / F捕获输出,以便您可以在父进程中设置值。但是你需要延迟扩张。

注意 - 这个例子非常简单,但它应该明白

for /f "delims=" %%A in ('cmd /v:on /c "set var=hi&echo "var=!var!""') do set %%A

但就确定引用内容,需要转义的内容,......而言,事情会变得复杂......

如果您创建一个完成工作并使用FOR / F执行它的批处理脚本,则可以简化生命。

<强> test.bat的

@echo off
set var1=hi
set var2=Ain't this fun
set var3=bye
setlocal enableDelayedExpansion
for %%V in (var1 var2 var3) do echo "%%V=!%%V!"

<强> main.bat

@echo off
for /f "delims=" %%A in ('cmd /c test.bat') do set %%A

实际上,FOR / F使用隐式CMD / C,您不再需要在命令中启用延迟扩展,因此您可以放弃显式CMD / C

@echo off
for /f "delims=" %%A in ('test.bat') do set %%A

如果您无法控制输出,则必须将值写入主脚本可以加载的临时文件。您可能想要编写一个定义变量的临时批处理脚本,但是您可能会遇到必须转义某些字符的风险,具体取决于变量的内容。最安全的选择是使用延迟扩展来写出变量名称和值,并让父进程使用FOR / F加载它们。

<强> test2.bat

@echo off
set var1=hi
set var2=Ain't this fun
set var3=bye
echo Here is some output that must be preserved, unrelated to variables
setlocal enableDelayedExpansion
(for %%V in (var1 var2 var3) do echo "%%V=!%%V!") >"%temp%\vars.temp"

<强> main.bat

@echo off
setlocal disableDelayedExpansion
cmd /c test2.bat
call "%temp%\vars.bat"
for /f "usebackq delims=" %%V in ("%temp%\vars.temp") do set "%%V"
del "%temp%\vars.temp"

请注意,在加载变量时,必须在主过程中禁用延迟扩展,否则在展开!时,您将丢失值中的所有%%V个字符。

但为了保持健壮,你应该做些什么来确保每个实例化使用一个唯一的临时文件名,这样同时运行就不会破坏彼此。