为什么对批处理文件中的算术表达式求值会产生预期的结果?

时间:2018-09-04 09:46:25

标签: batch-file variables

我的批处理脚本用于测量网络可以处理的两台PC之间的流量。因此,脚本确定文件的大小,然后将其从一台PC发送到另一台PC,并计算该文件可以工作多少次。但是,在计算成功传输的字节总数时存在一个怪异的问题。计算后通过asdf3打印的环境变量echo的值似乎不准确。

echo hat %count% mal geklappt
echo size: %menge% byte
set /a asdf3=%count%*%menge%
echo es wurden %asdf3% byte verschoben

上面的行产生以下输出:

hat 58 mal geklappt
size: 30245 byte
es wurden 2722050 byte verschoben

如果我的数学没问题,应该为1754210(58 * 30245)。

变量的初始化如下:

set file="test.odt"
FOR /F "usebackq" %%A IN ('%file%') DO set /A menge=%%~zA

set /A count=0
:marker
COPY /Y /V %file% \\%name%\Users\public
if 0==%errorlevel% (
    set/Acount=%count%+1
    goto :marker
)

为什么对批处理文件中的简单算术表达式求值会产生2722050而不是预期结果1754210

1 个答案:

答案 0 :(得分:1)

  1. 请勿使用语法set variable="value"。最好使用语法set "variable=value"并按原样引用环境变量值,或者将其与固定字符串或双引号中包含的其他环境变量引用串联在一起。还请查看关于Why is no string output with 'echo %var%' after using 'set var = text' on command line?的答案,它甚至更详细地说明了为什么最好使用set "variable=value"并在变量名的第一个"之前使用for /F

  2. 请勿使用专为逐行处理文本文件,命令行的字符串或捕获的输出而设计的set /A来获取文件的属性。

  3. 请勿使用%errorlevel%,这会导致将行的其余部分解释为算术表达式,从而仅定义环境变量,该变量始终在内存中为string类型值。

  4. 只要成功复制文件,循环就会无限循环。真的想要吗?

  5. 避免将if errorlevel X与命令 IF 一起使用,因为存在语法X用于测试先前命令或应用程序的退出代码是否大于或等于{{ 1}}或if not errorlevel X来测试上一条命令的退出代码是否低于X,这意味着通常等于0,因为命令和应用程序不存在负值。

  6. set/A之间缺少空格字符,而/Acount=%count%+1之间缺少空格字符。

  7. 在命令提示符窗口中运行set /?时获得的帮助输出为set /A解释了可以在算术表达式中使用其名称而不用%或{引用环境变量{1}},只要环境变量名称不包含算术运算符,定界符(例如空格或逗号)且不会错误地解释为整数即可。

  8. Windows命令处理器使用32位有符号整数算术,因此值范围为-2147483648至+2147483647。这意味着结合文件大小,在算术表达式的求值发生未处理或报告的溢出之前,值范围限制为2 GiB,几乎总是导致意外结果。有关更多详细信息,请参见:weird results with IF

  9. 除了特殊标签!之外,无需在 GOTO 命令行上指定以冒号开头的标签。有关详细信息,请参见Where does GOTO :EOF return to?

这是您的代码,无需其他代码即可重写,以解决32位带符号整数限制。

:EOF

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • set "name=127.0.0.1" set "file=test.odt" for %%A in ("%file%") do set "menge=%%~zA" set "count=0" :marker if %count% == 100 goto Output COPY /Y /V "%file%" "\\%name%\Users\public" if not errorlevel 1 set /A "count+=1" & goto marker :Output echo hat %count% mal geklappt echo size: %menge% bytes set /A asdf3=count * menge echo es wurden %asdf3% bytes verschoben
  • copy /?
  • echo /?
  • for /?
  • goto /?
  • if /?

有关运算符set /?的说明,另请参见Single line with multiple commands using Windows batch file