Почему вычисление арифметического выражения в пакетном файле приводит к непредвиденному результату? - PullRequest
0 голосов
/ 04 сентября 2018

Мой пакетный скрипт написан для измерения объема трафика между двумя компьютерами в сети. Таким образом, сценарий определяет размер файла и отправляет его с одного компьютера на другой и подсчитывает, сколько раз это работает. Но есть странная проблема с подсчетом общего количества успешно переданных байтов. Значение переменной среды 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 голосов
/ 04 сентября 2018
  1. Не используйте синтаксис set variable="value". Лучше использовать синтаксис set "variable=value" и ссылаться на значение переменной среды как есть или объединять его с фиксированной строкой или другой ссылкой на переменную среды, заключенной в двойные кавычки. Пожалуйста, взгляните также на ответ по Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке? Это объясняет еще больше деталей, почему лучше использовать set "variable=value" с первым " слева от имени переменной.

  2. Не используйте for /F, предназначенный для построчной обработки текстового файла, строки или захваченного вывода командной строки, чтобы просто получить свойство файла.

  3. Не используйте set /A, что приводит к интерпретации остальной части строки как арифметического выражения , чтобы просто определить переменную среды, которая всегда имеет тип string в памяти со значением.

  4. Цикл работает бесконечно, пока копирование файла успешно. Это действительно нужно?

  5. Избегайте использования %errorlevel% с командой IF , поскольку существует синтаксис if errorlevel X для проверки, является ли код завершения предыдущей команды или приложения большим или равным X или if not errorlevel X для тестирования, если код завершения предыдущей команды меньше X, что обычно равно 0, поскольку команды и приложения не существуют с отрицательным значением.

  6. Отсутствует пробел между set и /A и еще один между /A и count=%count%+1.

  7. Вывод справки при запуске set /? в окне командной строки объясняет для set /A, что на переменные среды можно ссылаться в арифметическом выражении только с их именем без % или !, пока имя переменной среды не содержит арифметического оператора, разделителя, такого как пробел или запятую, и не может быть ошибочно интерпретировано как целое число.

  8. Командный процессор Windows использует 32-разрядную целочисленную арифметику со знаком, поэтому диапазон значений от -2147483648 до +2147483647. Это означает, что в сочетании с размером файла диапазон значений ограничен 2 ГБ до того, как произойдет необработанное или сообщенное переполнение при вычислении арифметического выражения, приводящее почти всегда к неожиданным результатам. Для получения более подробной информации смотрите: странные результаты с IF

  9. Нет необходимости указывать в командной строке GOTO метку с двоеточием в начале, кроме специальной метки :EOF. Подробнее см. Куда возвращается GOTO: EOF?

Вот ваш код, переписанный без дополнительного кода, чтобы обойти ограничение 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

Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.

  • copy /?
  • echo /?
  • for /?
  • goto /?
  • if /?
  • set /?

См. Также Одна строка с несколькими командами с использованием пакетного файла Windows для объяснения оператора &.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...