为什么 SET /A 在 IF 语句后没有按预期工作?

Why is SET /A not working as expected after IF statement?

变量 _dd_mm 保存当前日期和月份。必须将 3 添加到当前日期,如果日期大于 27,则必须将 1 添加到月份(将其更改为提前一个月)。

Set /A _dd=%_dd%+3
REM **Set /A _mm=%_mm%+1**
echo %_dd%
IF %_dd% LSS 10 Set _dd=0%_dd%
IF %_dd% GTR 27 (
 Set _dd=01
 Set /A _mm=%_mm%+1
 Set _mm=0%_mm%
 Echo !_mm%! )
当 运行 在 IF 语句之外时,

Set /A _mm=%_mm%+1 有效,但在 IF 语句中不起作用。

为什么 SET /A 命令行在 IF 语句后没有按预期工作?

这里的问题很少。您正试图在没有 setlocal enableDelayedExpansion 子句的情况下使用延迟扩展。使用给定的测试数据,您永远不会输入最后一个 IF。您在没有正确使用 delayed variable expansion 的情况下在方括号块内设置值。最好使用 setlocal/endlocal 块。检查这个:

@echo off
:: to use variable expansion with ! you need delayed expansion
setlocal enableDelayedExpansion
Set /A _dd=%_dd%+3
REM **Set /A _mm=%_mm%+1**
echo %_dd%
IF %_dd% LSS 10 Set _dd=0%_dd%
echo %_dd%


::set another value to _dd to match  the last if condition
set /a _dd=30
::::



IF %_dd% GTR 27 (

 Set _dd=01
 Set /A _mm=_mm+1
 Set _mm=0!_mm!
 Echo !_mm%! 

)
endlocal

问题,(看来您几乎已经意识到),是变量扩展需要在 If 块中延迟。

Set /A _dd +=3
:: Set /A _mm +=1
Echo %_dd%
If %_dd% Lss 10 Set "_dd=0%_dd%"
IF %_dd% Gtr 27 (
   Set "_dd=01"
   Set /A _mm +=1
  Set "_mm=0!_mm!"
  Echo !_mm! )

在使用延迟扩展之前,您需要确保已启用它:

SetLocal EnableDelayedExpansion

在预处理以 ( 开始并以 IF 之前的匹配 ) 结束的整个命令块期间,将替换所有出现的 %_mm%条件完全由 Windows 命令解释器执行。这种行为可以通过 运行 在命令提示符 window 中处理批处理文件看到,顶部没有 @echo off 以在执行前预处理后获得命令行和整个命令块的输出。

看起来在同一命令块中访问正在修改的命令块中的环境变量时需要延迟环境变量扩展并不完全未知,因为 Echo !_mm%! 行表明尽管在语法上是错误的。打开命令提示符 window、运行 set /? 并仔细完整地阅读 window 中的帮助输出。在 IFFOR 示例中,命令 SET 的帮助解释了延迟环境变量扩展命令方块是最常用的。 SET的帮助也详细解释了算术表达式。

这是一个不使用延迟环境变量扩展的解决方案,它使用不同的流程来处理正确的月份值 0809。详情见第二个评论区。

rem This integer increment is problematic in case of value is 08 or 09.
rem See the month increment below how to handle such values also correct.
set /A _dd+=3
echo %_dd%

if %_dd% LEQ 27 goto MakeTwoDigitDay
set "_dd=01"

rem 08 and 09 would be interpreted as invalid octal numbers. Therefore do a
rem string concatenation with 1 if the first character is a leading zero for
rem month to change month value from 01-09 to 101-109 to get the month value
rem with a leading 0 interpreted as decimal number and add 1. Otherwise add
rem 101 to months 1-12 with no leading 0. Then assign to month variable
rem just the last two digits of the month value being greater than 100.

if "%_mm:~0,1%" == "0" ( set /A "_mm=1%_mm% + 1" ) else ( set /A "_mm+=101" )
set "_mm=%_mm:~-2%"
echo %_mm%

:MakeTwoDigitDay
if "%_dd:~1%" == "" set "_dd=0%_dd%"

要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • echo /?
  • goto /?
  • if /?
  • rem /?
  • set /?