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

Batch file 为什么对批处理文件中的算术表达式求值会产生不期望的结果?,batch-file,variables,Batch File,Variables,我编写的批处理脚本用于测量网络可以处理两台PC之间的通信量。因此,脚本确定文件的大小,并将其从一台PC发送到另一台PC,然后计算此操作的次数。但是,在计算成功传输的字节总数时存在一个奇怪的问题。计算后通过echo打印的环境变量asdf3的值似乎不准确 echo hat %count% mal geklappt echo size: %menge% byte set /a asdf3=%count%*%menge% echo es wurden %asdf3% byte verschoben 上

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

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

  • 不要使用语法
    set variable=“value”
    。最好使用语法
    设置“variable=value”
    并按原样引用环境变量值,或将其与固定字符串或另一个环境变量引用连在一起,并用双引号括起来。还请查看答案,其中解释了更多细节,说明了为什么最好使用
    将“variable=value”
    设置为第一个
    保留为变量名

  • 不要使用为逐行处理文本文件、字符串或捕获的命令行输出而设计的
    for/F
    ,仅获取文件的属性

  • 不要使用
    set/A
    ,这会导致将行的其余部分解释为算术表达式,仅定义一个环境变量,该变量在内存中始终为字符串类型,并带有一个值

  • 只要复制文件成功,循环就会无休止地运行。真的需要这样吗

  • 避免将
    %errorlevel%
    与命令IF一起使用,因为有语法
    IF errorlevel X
    用于测试上一个命令或应用程序的退出代码是否大于或等于
    X
    IF not errorlevel X
    用于测试上一个命令的退出代码是否低于
    X
    ,这意味着通常等于
    0
    ,因为命令和应用程序不存在负值

  • set
    /a
    之间缺少一个空格字符,
    /a
    count=%count%+1
    之间缺少一个空格字符

  • 在命令提示窗口中运行
    set/?
    时的帮助输出为
    set/a
    说明,只要环境变量名称不包含算术运算符delim,就可以在算术表达式中引用环境变量,只使用它们的名称,而不使用
    %
    iter就像一个空格或逗号,不能被错误地解释为整数

  • Windows command processor使用32位有符号整数算术,因此值范围为-2147483648到+2147483647。这意味着结合文件大小,在计算算术表达式时发生未处理或报告的溢出之前,值范围限制为2 GiB,几乎总是导致意外结果。对于详情请参阅:

  • 除了特殊标签
    :EOF
    ,无需在GOTO命令行中指定开头带有冒号的标签。有关详细信息,请参阅

  • 这里是您的代码重写,没有额外的代码来解决32位有符号整数限制

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

    • 复制/?
    • echo/?
    • 获取/?
    • goto/?
    • 如果/?
    • 设置/?

    有关运算符
    &

    无法再现此类行为的解释,请参见,但您需要在
    设置/a count=%count%+1
    中留出一个空间。顺便说一句,相同的
    设置/a count=count+1
    或更好的
    设置/a count+=1
    如果您有大文件,因为cmd仅使用32位,这将不起作用。感谢您的帮助,现在脚本可以工作了是的,循环被设计成无止境的,因为我希望系统崩溃只是为了看看它能提供的最大速度。