“SET 命令设置的环境变量在 FOR 循环中始终为空”问题的原因与解决方法

问题 | Issue/Problem/Question

我在 FOR 循环中用 SET 为一个环境变量赋值,结果发现该变量始终为空内容,不知何故 比如在下面的代码中: 1、第一个 for 语句我是打算取得 YYMMDD 格式的日期字符串: TODAY_FOLDER,在 for 语句内部的 SET TODAY_FOLDER 语句得不到 TODAY 的值,然而如果放在 for 语句后面就可以 2、第二、第三两个嵌套 for 语句我打算得到一组 IP 地址,然而 echo 用户端IP是%THE_CLIENT_IP% 得到的仍然是空的 代码: @echo off REM ******************************* REM FileName: test.cmd REM OS: Windows 2000 Professional REM Author: "刘研|LiuYan" REM DATE: 2006年04月06日 | 04/06/2006 REM ******************************* setlocal FOR /F "tokens=1-3 delims=- " %%i IN ('date /t') DO ( SET TODAY=%%i%%j%%k SET TODAY_FOLDER=%TODAY:~2% echo 今天的文件夹:%TODAY_FOLDER% ) REM IP 段:15?-18?,其中 ? 取值范围 [1-9](因每排只有 9 个) for /L %%i in (5,1,8) do ( for /L %%j in (1,1,9) do ( SET THE_CLIENT_IP=192.168.115.1%%i%%j echo %ERRORLEVEL% ClientIP=[%THE_CLIENT_IP%] 192.168.115.1%%i%%j ) ) endlocal @echo on

解决方法 1 | Solution 1

  1. 修改批处理脚本:在 for、if 语句体中,如果要使用在本语句体由 SET 命令设置的“局部”环境变量,则需要使用 !环境变量名! 的形式来取得它的值,而不能使用传统的 %环境变量名% 形式
  2. 启动一个单独 cmd.exe 实例来启动该批处理脚本,并在 cmd.exe 启动参数中添加 /V:ON 选项,只有打开 /V:ON 选项,才能使得 !环境变量名! 形式的取值生效。如果需要,可添加 /C 参数使 cmd.exe 在执行完后自动退出

修改后的代码

代码: @echo off REM ******************************* REM FileName: test2.cmd REM OS: Windows 2000 Professional REM Author: "刘研|LiuYan" REM DATE: 2006年04月06日 | 04/06/2006 REM ******************************* echo 必须启用 cmd.exe 的 /V:ON 选项 ^| You must open the /V:ON swith/option of cmd.exe setlocal FOR /F "tokens=1-3 delims=- " %%i IN ('date /t') DO ( SET TODAY=%%i%%j%%k SET TODAY_FOLDER=!TODAY:~2! echo 今天的文件夹:!TODAY_FOLDER! ) for /L %%i in (5,1,8) do ( for /L %%j in (1,1,9) do ( SET THE_CLIENT_IP=192.168.115.1%%i%%j echo ClientIP=[!THE_CLIENT_IP!] 192.168.115.1%%i%%j ) ) endlocal @echo on

执行该批处理文件

C:/>cmd /V:ON /C test.cmd

解决方法 2 | Solution 2

或者,如果你不喜欢 /V:ON 选项/参数,那么可以试试:CALL 另外一个脚本

修改后的代码

代码: @echo off REM ******************************* REM FileName: test3.cmd REM OS: Windows 2000 Professional REM Author: "刘研|LiuYan" REM DATE: 2006年04月06日 | 04/06/2006 REM ******************************* setlocal FOR /F "tokens=1-3 delims=- " %%i IN ('date /t') DO ( CALL :label_Sub_SetTodayFolder %%i %%j %%k REM 不过,下面这一句仍然无法得到 TODAY、TODAY_FOLDER 的值 REM echo 今天是:%TODAY%,今天的文件夹:%TODAY_FOLDER% ) for /L %%i in (5,1,8) do ( for /L %%j in (1,1,9) do ( CALL :label_Sub_SetClientIP %%i %%j ) ) endlocal @echo on @goto :EOF :label_Sub_SetTodayFolder SET TODAY=%1%2%3 SET TODAY_FOLDER=%TODAY:~2% echo 今天是:%TODAY%,今天的文件夹:%TODAY_FOLDER% goto :EOF :label_Sub_SetClientIP SET THE_CLIENT_IP=192.168.115.1%1%2 echo ClientIP=[%THE_CLIENT_IP%] goto :EOF

总结/说明 | Summary/Description

该问题起因于未启用 cmd.exe 的 /V:ON 选项(cmd.exe 默认的是 /V:OFF),/V:ON 选项将禁用“环境变量的延迟生效”,如果不启用该选项,则环境变量在诸如 if、for 语句体内的值不会实时的取得

参考文档 | References

  1. C:/>help cmd
  2. (Windows2000 Command Processor FAQ) 列举了很多例子 http://www.microsoft.com/technet/prodtechnol/Windows2000serv/support/FAQW2KCP.mspx (WindowsXP cmd) http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/cmd.mspx?mfr=true (WindowsServer2003 cmd) http://www.microsoft.com/technet/prodtechnol/windowsserver2003/zh-chs/library/ServerHelp/d0518719-7154-49b4-954c-0a6c015ab441.mspx?mfr=true
  3. (CSDN上本人发的求助帖,感谢 meidog(meidog)、spark_li(晕忽忽(恶人谷:通讯连长)) 两位热心 csdn 网友的帮助) http://community.csdn.net/Expert/topic/4661/4661135.xml
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页